Oct 29

Integrating IBM i CGI programs into Linux Web Server

We have been working with a number of clients now who have CGI programs (mainly RPG) that have been used as part of web sites which were hosted on the IBM Apache Server. These programs build the page content using a write to StdOut process. They have now started the migration to PHP based web sites and need to keep the CGI capability until they can re-write the existing CGI application to PHP.

The clients are currently running the iAMP server (they could use the ZendServer as well) for their PHP content and will need to access the CGI programs from that server. We wanted to test the process would run regardless of the Apache server used (IBM i, Windows,Linux etc) so we decided to set up the test using our Linux Apache server. The original PHP Server on the IBM i used a process that involved the passing of requests to another server (ProxyPass) which is what we will use to allow the Linux Server to get the CGI content back to the originating request. If you want to know more about the Proxy Process you can find it here.

First of we set up the IBM Apache Server to run the CGI program which we need. The program is from the IBM knowledge center called SampleC which I hacked to just use the POST method (code to follow) which I complied into a library called WEBPGM. Here is the content of the httpd.conf for the apachedft server.

# General setup directives
HotBackup Off
TimeOut 30000
KeepAlive Off
DocumentRoot /www/apachedft/htdocs
AddLanguage en .en
DefaultNetCCSID 819
Options +ExecCGI -Includes
ScriptAliasMatch ^/cgi-bin/(.*).exe /QSYS.LIB/WEBPGM.LIB/$1.PGM

The Listen line states that the server is going to listen on port 8081. Options allows the execution of CGI progrmas (+ExecCGI). I have set the CGI CCSID and conversion mode and then set up the re-write of any request that has a url with ‘/cgi-bin/’ and has a extension of .exe to the library format required to call the CGI program.

The program is very simple, I used the C version of the program samples IBM provides and hacked the content down to the minimum I needed. I could have altered it even further to remove the write_data() function but it wasn’t important. Here is the code for the program which was compiled into the WEBPGM lib.

#include <stdio.h> /* C-stdio library. */
#include <string.h> /* string functions. */
#include <stdlib.h> /* stdlib functions. */
#include <errno.h> /* errno values. */
#define LINELEN 80 /* Max length of line. */

void writeData(char* ptrToData, int dataLen) {
div_t insertBreak;
int i;

for(i=1; i<= dataLen; i++) {
insertBreak = div(i, LINELEN);
if( insertBreak.rem == 0 )

void main( int argc, char **argv) {
char *stdInData; /* Input buffer. */
char *queryString; /* Query String env variable */
char *requestMethod; /* Request method env variable */
char *serverSoftware; /* Server Software env variable*/
char *contentLenString; /* Character content length. */
int contentLength; /* int content length */
int bytesRead; /* number of bytes read. */
int queryStringLen; /* Length of QUERY_STRING */

printf("Content-type: text/html\n");
printf("Sample AS/400 HTTP Server CGI program\n");
printf("<h1>Sample AS/400 ILE/C program.</h1>\n");
printf("<br>This is sample output writing in AS/400 ILE/C\n");
printf("<br>as a sample of CGI programming. This program reads\n");
printf("<br>the input data from Query_String environment\n");
printf("<br>variable when the Request_Method is GET and reads\n");
printf("<br>standard input when the Request_Method is POST.\n");
requestMethod = getenv("REQUEST_METHOD");
if ( requestMethod )
printf("<h4>REQUEST_METHOD:</h4>%s\n", requestMethod);
printf("Error extracting environment variable REQUEST_METHOD.\n");
contentLenString = getenv("CONTENT_LENGTH");
contentLength = atoi(contentLenString);
if ( contentLength ) {
stdInData = malloc(contentLength);
if ( stdInData )
memset(stdInData, 0x00, contentLength);
printf("ERROR: Unable to allocate memory\n");
printf("<h4>Server standard input:</h4>\n");
bytesRead = fread((char*)stdInData, 1, contentLength, stdin);
if ( bytesRead == contentLength )
writeData(stdInData, bytesRead);
printf("<br>Error reading standard input\n");
printf("<br><br><b>There is no standard input data.</b>");
serverSoftware = getenv("SERVER_SOFTWARE");
if ( serverSoftware )
printf("<h4>SERVER_SOFTWARE:</h4>%s\n", serverSoftware);
printf("<h4>Server Software is NULL</h4>");

Sorry about the formatting!

That is all we had to do on the IBM i server, we restarted the default apache instance and set to work on creating the content required for the Linux Server.
The Linux Server we use is running Proxmox, this allows us to build lots of OS instances (Windows,Linux etc) for testing. The Virtual Server is running a Debian Linux build with a standard Apache/PHP install. The Apache servers are also running Virtual hosts (we have 3 Virtual Linux servers running Apache), this allows us to run many websites from a single server/IP address. We created a new server called phptest (www.phptest.shield.local) running on port 80 some time ago for testing our PHP scripts so we decided to use this server for the CGI test. As the Server was already running PHP scripts all we had to do was change the configuration slightly to allow us to pass the CGI requests back to the IBM i Apache server.

The sample code provided by IBM which will run on the Linux Server is listed below.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>

<form method="POST" action="/cgi-bin/samplec.exe">
<input name="YourInput" size=42,2>
Enter input for the C sample and click <input type="SUBMIT" value="ENTER">
<p>The output will be a screen with the text,
"YourInput=" followed by the text you typed above.
The contents of environment variable SERVER_SOFTWARE is also displayed.

When the url is requested the following page is displayed.


Sample C input page

The Server needs to know what to do with the request so we have to redirect the request from the Linux Server to the IBM i server using the ProxyPass capabilities. You will notice from the code above that we are using the POST method from the form submission and we are going to call ‘/cgi-bin/samplec.exe’. This will be converted on the target system to our program call. The following changes were made to the Linux Apache configs and the server was restarted.

ProxyPreserveHost On
ProxyPass /cgi-bin/
ProxyPassReverse /cgi-bin/

This allows the Linux Server to act as a gateway to the IBM i Apache server, the client will see the response as if it is from the Linux server.
When we add the information into the input field on the page and press submit the following is displayed on the page.

Output from CGI program

Those reading carefully will notice the above page shows a url of www1.phptst.shield.local not www.phpest.shield.local as shown in the output screen below. This is because we also tested the iAMP server running on another IBM i to link to the same IBM Apache Server used in the Linux test using exactly the same code.

This is a useful setup for being able to keep existing CGI programs which are being presented via the IBM Apache Server while you migrate to a new PHP based interface. I would rather have replaced the entire CGI application for the clients with a newer and better PHP based interface, but the clients just wated a simple and quick fix, maybe we will get the opportunity to replace it later?

The current version of iAMP which available for download from the Aura website does not support mod_proxy so if this is something you need to implement let us know and we can supply a version which contains the mod_proxy modules. I hope Aura will update the download if sufficient people need the support which will cut us out of the loop.

If you need assistance creating PHP environments for IBM i let us know. We have a lot of experience now with setting up PHP for IBM i and using the Easycom toolkit for access IBM i data and objects.


Jun 05

What does V8R0 of HA4i look like?

While we wait for IBM to get back to us about our PowerVM activations (3 days and counting, I often wonder does IBM want to service clients?) I thought I would start to show some of the changes we have made in the next release of HA4i. The announcement date for the next release is a little way off as we still have to get the manual and new PHP interfaces finished, but we all feel excited about some of the new capabilities so we thought we would start to share.

As the PHP interface is not completed and we have found the IBM Access for Web product is performing very well, we thought it would be an ideal opportunity to show it off at the same time we display some of our new features. So far the displays have been pretty pleasing with no problems in showing the content effectively. Again we will point out the fact that the web interface is being run on one system (shield7) and the system running HA4i is another (shield8), the ability to launch a 5250 session from the web interface to another system without the web software running on that system is pretty neat in our view.

The first screen we will share is the main monitoring screen, this is a screen shot of the 5250 green screen output using the standard Client Access emulator.

5250 Roleswap Status Green screen

5250 Roleswap Status Green screen

Here is the IBM Access for Web output of the same screen, we have placed arrows and markers to show some of the features which we will describe below.

Roleswap Status Access for Web

Roleswap Status Access for Web

Arrow 1.
A)These are the options that are available against each of the environment definitions, these can be used to drill down into more specific data about each of the processes involved in the replication of the objects and data.

B)You will notice that we can end and start each environment separately, there is also an option on the operations menu which will start and stop every environment at once.

C) You can Roleswap each individual environment, the previous version only allowed a total system Roleswap.

Arrow 2.
A) Some environments should not allow Roleswaps to be carried out, we have defined 2 such environments to replicate the JQG4i data. Because the data is only ever updated on the generating system and each system has its own data sets you would never want to switch the direction of replication. The Y/N flags show that the BATCHTST environment can be switched while the JQG4i environments cannot.

Arrow 3.
A) These are the environment names, each environment runs its own configurations and processes.

Arrow 4.
A) This is the mode of the environment on this system *PROD states that this is a source system where the object changes are captured while the *BACKUP is where the changes will be applied. when viewing the remote system these roles will be reversed.

Arrow 5.
A) If there are any errors or problems found within any of the replication processes you should not carry out a roleswap, HA4i retrieves the status from both the local and remote system to determine if an environment is capable of being roleswapped based on the state of the replication processes. As you can see if an environment should not be roleswapped the entry is marked as *NA.

Arrow 6/7/8.
A) This is the state of the various replication processes, *GOOD states that there are no errors and everything that should be running is. *NOCFG states that no configurations exist that require the replication process to be running. Data status is the journal apply process and which could encompass more than one apply process if there is more than one journal configured to the environment.

Arrow 9.
A) You can view the configs from any system but changes to the configs can only be carried out on the *BACKUP system. the configuration pages can be accessed using this button (F17 on the 5250 Green screen).
B) The Remote Sys button (F11 on the 5250 green screen) just displays the remote system information.

There are a lot more new features in the next release which will make HA4i more competitive in complex environments, over the next few weeks/months we will show you what they are and why they are important. The big take away from above is the ability to define a much more granular approach to your replication needs. Becuase we can define multiple systems and multiple environments HA4i is going to be a lot more useful when you need to migrate to new hardware and expand data replication beyond 2 systems.

We hope that you like the features and if you are looking at implementing a new HA solution or looking to replace an existing one that you consider HA4i.


Jun 05

IBM i Mobile with IBM i Access for Web

We have been resistant to implement anything to do with the IBM HTTP server for a number of reasons, the main one being that we feel Linux is a better option for running any HTTP services on. However when we heard that IBM was now providing a mobile interface for the IBM i as part of the 7.2 release we felt we should take a closer look and see if it was something we could use. To our surprise we found the initial interaction very smooth and fast.

Installation was fairly simple other than the usual I don’t need to read the manuals part! We had installed 7.2 last week with the intention of reviewing the mobile access, unfortunately we did not realize that there were already Cum PTF’s and PTF Groups available. Our first try at the install stopped short when we thought Websphere was a requirement, as it turns out it can be used but is not a prerequisite. Thanks to a LinkedIn thread we saw and responded to our misconception was rectified and we set about trying to set up the product again. We followed all of the instructions (other than making sure the HTTP PTF Group was installed :-() and it just kept giving us a 403 Forbidden message for /iamobile. Took a lot of rummaging through the IFS directories to find out that when the CFGACCWEB command run it logged the fact that a lot of directories were missing (even though the message sent when it completed stated it completed successfully, maybe IBM should look at that?) so we reviewed all of the information again. It turns out the Mobile support is delivered in the PTF Group so after downloading and installing the latest CUM plus all of the PTF Groups we found the interface now works.

As I mentioned at the beginning I am surprised at just how snappy it is, we don’t have hundreds of users but our experience of the Systems Director software for IBM i made us very wary about actually using anything to do with the IBM i HTTP servers so we had no high expectations of this interface. We saw no lag at all in the page requests and the layout is very acceptable. When the time came to enter information the screen automatically zoomed into the entry fields (I like that as my eye sight is not what it used to be). We looked at a number of the screens but have not gone through every one. I really like the ability to drill down into the IFS and view a file (no edit capability) which will be very useful for viewing logs in the IFS.

Here are a few of the screen shots we took, the first set is from an iPod the second is from the iPad, we were going to try the iPhone but the iPod is the same size output so jsut stuck with testing from the iPod (yes we like Apple products, we would get off our Microsoft systems if IBM would release the much rumored RDi for the MAC). I think IBM did a good job in the page layouts and content.

iPod Display of file in IFS.

iPod Display of file in IFS.

iPod display of messages

iPod display of messages

iPod SQL output

iPod SQL output

iPod sign on screen shield7

iPod sign on screen shield7

iPod 5250 session

iPod 5250 session

iPod initial screen

iPod initial screen

The iPad screens.

iPad Display of messages on Shield7

iPad Display of messages on Shield7

iPad 5250 session, note how it is connected to another system (shield6)

iPad 5250 session, note how it is connected to another system (shield6)

iPad SQL output

iPad SQL output

iPad List of installed Licensed Programs

iPad List of installed Licensed Programs

iPad initial page

iPad initial page

Clicking on the images will bring up a larger one so if like me you are a bit blind you can see the content. Also take notice of the 5250 connection to the Shield6 system, Shield6 is not running the mobile access or the HTTP server so we were surprised when we could start a session to the Shield6 system using the mobile access from the Shield7 system. I definitely think this is a big improvement on anything else we have seen in terms of speed using the IBM HTTP server.

If you don’t have the Mobile support installed do it now! the fact that it is PTF’d all the way back to V6R1 is a big benefit. We will certainly be adopting this as our preferred access method from our mobile devices especially to provide support from our mobile devices while we are away from the office.


Aug 23

Sending emails with attachments from the IBM i

OK I have to admit I did not think of this first, I found it when I checked the latest Blog postings on iPlanet! You can find the original here. I just searched on the web to find the IBM documentation which is located here.

The reason I was really interested was due to a client issue where the iAMP server does not have any built in email function (mail()), so I was looking at how to build my own email function.

The functions I built were based on the code we produced for our HA4i product which has an inbuilt email manager for its notification process, these are written in C and use the low level socket functions to send the email directly to a SMTP server. Nothing fancy but it does work and as we are not email guru’s we thought keeping it simple was out best option. All went well until we though about adding attachments to the email, the HA4i code has no ability to add attachments because it does not need it. After a lot of reading and combing through RFC’s and Wiki pages we found the solution we needed, multipart mime was needed so we had to structure the code to allow the attachments to be correctly embedded into the email body.

After some trial and error we did get the process to work and we now have correctly formatted emails with attachments being sent from the IBM i. But we wanted to see if there are other options (we like options :-)) which is how we came across the above blog post. Running the command in a CL program etc was not what we needed, we wanted to provide a PHP version. Thankfully the i5_toolkit provides the answer, we just needed to call the command via the i5_command() function! Here is the sample code we used to test it with.

The page which is called connects to the IBM i and then uses the following to call the function

send_email_cmd($conn,"chrish@shieldadvanced.ca","This is a test message with IBM Command","/home/CHRISH/mail-1.2.0.tar");

This if the code for the function

function send_email_cmd(&$conn,$recipient,$subject,$file) {
$command = "SNDSMTPEMM RCP((" .$recipient .")) SUBJECT('" .$subject ."') NOTE('

This is the body of the email

I can enter things using HTML and format things in a most pretty way

cool') ATTACH(('" .$file ."' *OCTET *BIN)) CONTENT(*HTML)";
if(!i5_command($command,$conn)) {
echo("Failed to submit command " .$command);
else {
echo("Successfully sent email");

That was all there was to it! You could add a lot more code to verify the attachment types etc etc etc but our test proved the functionality does work.
Thanks to Nick for pointing out the command.


May 31

Bob Cancilla’s off the mark!

I thought Bob Cancilla was actually changing his position on the need to pull away from the IBM i, but it looks like he has had yet another episode! You can find a copy of his latest rant here

Here are my views on his comments.

1. Yes the IBM i install base is dwindling, but that is not because of the platform not being supported by IBM. Companies Merge so the server technology changes and generally decreases through consolidation. Companies go bust and close their doors meaning the servers are no longer needed, if you haven’t noticed the last 5 – 10 years have not been growth years.

2. The fact that COMMON Europe cancelled its conference is not a sign that there are no IBM i installs out there, the economy in Europe is bad and budgets have been cut for everyone! He does not mention what other conferences for his platforms of choice have seen in terms of attendance etc. Having a conference in an exclusive French resort which is very expensive is not the best idea COMMON Europe made. IBM pulled out because sending people to Europe is expensive and the location chosen is obviously a major factor in their decision, especially when no one else was going!

3.The Nordic numbers are not backed up by the graphic in the link, so I assume the reduction in numbers is something he has from some other source? If there were 10,000 customers running IBM i was that systems or was that an actual customer count? Why concentrate on the Nordics as an indicator for the rest of the world? As I have said the numbers must be dwindling, but some of that has to be to do with the power of the newer systems. I personally had 3 systems running for our business until we purchased a new Power 6 system, all of them were in the P05 tier group! I now have a single system running 3 Partitions each of which are probably 3 – 4 times faster than the previous Power 5+ i515 system alone so I need a lot less systems to deliver better user experiences. If I went to a Power 7 this would be increased exponentially again!!! Others have obviously done the same as I did and reduced the number of servers.

4. IBM is getting out of hardware and has been since I worked at IBM Havant in 1975 – 1993, nothing has changed there. The fact that they are selling the x86 business is good for Power, if Power was the problem they would be getting rid of it! Yes IBM invested in Linux, but obviously not for x86 hardware (they are desperately trying to get out of that) so again it was probably for the Power hardware, so why are they doing that if it is being dropped. There are many other reasons such as services revenue and software licensing (Linux is not free at the Enterprise level) so it is a mix of everything above.

5. RPG locks you into the platform so it is bad, hmmmm then why not use one of the other languages available on the platform? You have a choice of many languages on the IBM i and my very personal opinion is that anyone who is just using RPG is cutting their own throat! RPG is just a tool in the toolbox, so pick the best tool for the job. If I am going to have to rebuild my entire application just to change the language why would I ever add a new platform and all of the complexities of the OS into the mix? I could train a ‘C’ developer on Linux to develop in ‘C’ on the IBM i a lot faster than I could train an RPG developer to develop in C on Linux, that goes for any language and the IBM i supports them all (especially Java). Even though RPG is a key tool on the IBM i we need to reduce the emphasis placed on it and start to push the other languages just as hard.

We are being told CLOUD is the next leap in faith for the IT community. If you are to believe the hype it means you are not interested in how the result is delivered and what produced it just that it is available all the time and at a lower cost. As usual there are lots of ideas on what this means in terms of application delivery and many of them are a new set of acronyms for the same technologies that refused to fly years ago. I have doubts if the Cloud is the answer and I am sure that before too long we will have a new word for it! Having said that, if the Cloud is the next evolution of IT delivery why does this do anything but create the need for stable, dependable, highly available, flexible systems (oh did I just explain what the IBM i is???). So while I appreciate Bobs right to keep trying to build his business using scare tactics and bluff, I for one will keep an open mind about dumping IBM i in favor of moving to something new.

Just to set the record straight, I run Windows, MAC, Linux, AIX and IBM i. I have spent a lot of time developing on Windows, Linux and IBM i (IBM i the most) and all in a single language ‘C’ (or the related object version). In my view IBM i is the simplest for many reasons, not least the integration of everything you need to build a total solution. I use PHP for interface building (80 column screens just don’t hack it for me) and prefer to run the Web Services from Linux or Windows, but the IBM i can perform as a web server if needed.

So if you do as Bob says and take a deep and meaningful look at your IT infrastructure, consider changing the development language before jumping to a new development language, platform, OS and development tool set! Remember with ILE you can build the solution out of many languages and they will all work in harmony so you can steadily replace older programs with new ones.


May 16

Pagination now added to log viewer

One of the tasks we left out in the initial release of the PHP Interface of FTP Guard4i was the ability to set the page size when viewing the log entries. What we wanted to do was allow the number of log records displayed to be preset by the user, this would allow the retrieval of records to the page to be carried out a lot quicker than if all of the records were to be displayed. As part of this exercise we also decided to add a search button for data stored in certain columns of the database, this would allow you to say filter the records based on a certain object or on a certain user etc. and still provide a paged output.

The following is a sample screen where the sort parameter is the date and time column, because we provided the sort capability we do not need a search capability as well so no search box is displayed.

Paged Log View

Paged Log View

Here is a sample screen showing the sort column being the Object information and the search value was QSYS.

Paged View with Search

Paged View with Search

We are constantly looking at ways to add new features and functionality to the FTP Guard4i product, if you have any questions or would like to see a demo please let us know.


May 06

FTP Guard4i is available for download

FTP Guard4i is now completed and available for download. We have placed the manuals online as well as the objects required to install the product. You will need to sign in as a member to download the objects and once installed you will need a key to allow the product to function. The PHP interface is available and requires the Easycom i5_toolkit functions to allow connectivity to the IBM i. We have not tested it with the Zend Free toolkit at this time and would need to make some additional changes due to the lack of support for some objects. If this is needed we can work with you to make those changes.

FTP Security is something we have been looking at for a long time, our initial requirement was highlighted because of the access to the source code for our products by the developers. We needed to give them access to the code to allow them to carry out their activities but we did not want them to be able to copy the code to other systems. The original product we created also provided an FTP Client so we could make the object transfer a lot easier than the FTP Client provided by the OS but this release only provides the security aspects required.

As part of the rewrite we have made a number of improvements in the methods we used to control the access particularly around the accept and reject IP addresses set for individual users. This allows you to set a range of IP addresses a user can connect to and from in the same manner as you can set the connection accept and reject addresses. We have also changed the logging to a Database file which allows us to add much more meaningful data about the activities carried out. While the clean up routines we have provided only allow the log to be cleared, using standard SQL against the file will provide a lot more granular entry removal.

FTP Security is an area most IBM i shops ignore because they believe the IBM i is naturally more secure than other platforms, that is not true and as we see more and more IBM i systems being linked to a wider audience we could see more intrusions being logged. FTP Guard4i also has a very comprehensive logging feature so you can now see who connects to your server and what they did while they were connected.

If you need more information about FTP Guard4i or would like to see a working demo please let us know using the demo request forms on the website.


Apr 24

FTP Guard4i Log Viewer

As promised we have now developed the log viewer which shows the events which have been logged by the FTP processes. The log view has a number of columns each of which is sortable but the default sort is done by the Date and Time with the latest entry at the top. Here is sample view of the log on our test server.

FTP Guard4i log view

A sample of the events logged by FTP Guard4i.

A couple of interesting things came about while generating the log, you will see that we deleted a file ‘/home/CHRISH/??_???????`%??>?>????????’, one of the issues we all come across from time to time is where a file in the IFS has a strange name, deleting the file using the normal IFS commands is not possible as it will always return ‘File not found’ errors. Using FTP (actually we used FileZilla) you can see that we successfully deleted the file in question. The log also shows a ‘Send File’ operation, that was actually a get operation from the FTP client but the event gets logged as a ‘Server Send File’ operation..

The PHP interface is now pretty much complete but we need to do some more work on the UIM interface to align the data store with the actual output to the UIM Manager. Once that is finished and we have done some more testing FTP Guard4i will be available for download.


Apr 23

FTP Guard 4i Take 2

We had been discussing the FTP Guard 4i with a prospect and they mentioned that they would like to be able to monitor the FTP Server and SFTP Server from the FTP interface. So we have added a couple of new features to the status screen that allow the user to administer the FTP Server and the SSHD server which is used for the SFTP connections.

Here is the new status screen

New FTP Guard 4i status screen

FTP Guard 4i take 2

One of the things we did notice when we added the new features and checked they functioned was the SFTP connection takes on the QSECOFR profile in the job and drops the original user profile. We need to take a look at this to see exactly what effect this has? We don’t allow the QSECOFR profile to connect via FTP or SFTP so the security we have set for the user as far as FTP is concerned still applied.

Let us know if you are interested in this kind of solution and what if any additional features you would like to see. The Log viewer is coming along and will be the subject of our next post.


Feb 12

Adding a Bar Graph for CPU Utilization to HA4i and DR4i

As part of the ongoing improvements to the PHP interfaces we have developed for HA4i and DR4i we decided to add a little extra to the dashboard display. The dashboard display is a quick view of the status for the replication processes, we used traffic lights as indicators to determine if the processes are running OK. Another post recently discussed using a gauge to display the overall CPU utilization for the system but we wanted to take it one step further, we wanted to be able to show just the CPU utilization for the HA4i/DR4i jobs.

We thought about how the data should be displayed and settled on a bar graph, the bars of the graph would represent the CPU utilization as a percentage of the available CPU and would be created for each job that was running in the HA4i/DR4i subsystem. This gave us a couple of challenges because we needed to determine just how many jobs should be running and then allow us to build a table which would be used to display the data. There are plenty of bar graph examples out there which show how to use CSS and HTML to display data, our only difference is that we would need to extract the data from the system and then build the bar graph based on what we were given.

The first program we needed to create was one which would retrieve the information about the jobs that are running that could be called from the Easycom program interface. We have already published a number of tests around this technology so we will just show you the code we added to allow the data to be extracted. To that end we extended the PHPTSTSRV service program with the following function.

typedef _Packed struct job_sts_info_x {
char Job_Name[10];
char Job_User[10];
char Job_Number[6];
int CPU_Util_Percent;
} job_sts_info_t;

int get_job_sts(int *num_jobs, job_sts_info_t dets[]) {
int i,rc = 0,j = 0; /* various ints */
int dta_offset = 0;
char msg_dta[255]; /* message data */
char Spc_Name[20] = "QUSLJOB QTEMP "; /* space name */
char Format_Name[8] = "JOBL0100"; /* Job Format */
char Q_Job_Name[26] = "*ALL HA4IUSER *ALL "; /* Job Name */
char Job_Type = '*'; /* Job Info type */
char *tmp;
char *List_Entry;
char *key_dta;
Qus_Generic_Header_0100_t *space; /* User Space Hdr Ptr */
Qus_JOBL0100_t *Hdr;
Qwc_JOBI1000_t JobDets;
EC_t Error_Code = {0}; /* Error Code struct */

Error_Code.EC.Bytes_Provided = _ERR_REC;
/* get usrspc pointers */
/* memcpy(Q_Job_Name,argv[1],26); */
if(Error_Code.EC.Bytes_Available > 0) {
if(memcmp(Error_Code.EC.Exception_Id,"CPF9801",7) == 0) {
/* create the user space */
if(Crt_Usr_Spc(Spc_Name,_1MB) != 1) {
printf(" Create error %.7s\n",Error_Code.EC.Exception_Id);
if(Error_Code.EC.Bytes_Available > 0) {
printf("Pointer error %.7s\n",Error_Code.EC.Exception_Id);
else {
printf("Some error %.7s\n",Error_Code.EC.Exception_Id);
if(Error_Code.EC.Bytes_Available > 0) {
printf("QUSLJOB error %.7s\n",Error_Code.EC.Exception_Id);
List_Entry = (char *)space;
List_Entry += space->Offset_List_Data;
*num_jobs = space->Number_List_Entries;
for(i = 0; i < space->Number_List_Entries; i++) {
Hdr = (Qus_JOBL0100_t *)List_Entry;
"*INT ",
if(Error_Code.EC.Bytes_Available > 0) {
printf("QUSRJOBI error %.7s\n",Error_Code.EC.Exception_Id);
dets[i].CPU_Util_Percent = JobDets.CPU_Used_Percent;
List_Entry += space->Size_Each_Entry;
return 1;

The program calls the QUSLJOB API to create a list of the jobs which are being run with a User profile of HA4IUSER (we would change the code to DR4IUSER for the DR4I product) and then use the QUSRJOBI API to get the CPU utilization for each of the jobs. We did consider using just the QUSLJOB API with keys to extract the CPU usage but the above program does everything we need just as effectively. As each job is found we are writing the relevant information to the structure which was passed in by the PHP program call.

The PHP side of things requires the i5_toolkit to call the program but you could just as easily (well maybe not as easily :-)) use the XMLSERVICE to carry out the data extraction. We first created the page which would be used to display the bar chart, this in turn calls the functions required to connect to the IBMi and build the table to display the chart. Again we are only showing the code which is additional to the code we have already provided in past examples. First this is the page which will be requested to display the chart.

Copyright © 2010, Shield Advanced Solutions Ltd
All rights reserved.


Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Neither the name of the Shield Advanced Solutions, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior written

// start the session to allow session variables to be stored and addressed
// load up the config data
if(!isset($_SESSION['server'])) {
$conn = 0;
$_SESSION['conn_type'] = 'non_encrypted';
if(!connect($conn)) {
if(isset($_SESSION['Err_Msg'])) {
$_SESSION['Err_Msg'] = "";
echo("Failed to connect");
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
td.value {
background-image: url(img/gl.gif);
background-repeat: repeat-x;
background-position: left top;
border-left: 1px solid #e5e5e5;
border-right: 1px solid #e5e5e5;
border-bottom: none;

td {
padding: 4px 6px;
border-bottom:1px solid #e5e5e5;
border-left:1px solid #e5e5e5;

body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 80%;

td.value img {
vertical-align: middle;
margin: 5px 5px 5px 0;

th {
text-align: left;

td.last {
border-bottom:1px solid #e5e5e5;

td.first {
border-top:1px solid #e5e5e5;

table {
background-position:left top;
width: 33em;

caption {

<?php get_job_sts($conn,"*NET"); ?>

The above code shows the STYLE element we used to form the bar chart, normally we would encompass this within a CSS file and include that file, but in this case as it is just for demonstrating the technology we decided to leave it in the page header. the initial code of the page starts up the session, includes the functions code, loads the config data which is used to make the connection to the IBMi and then connects to the IBMi. Once that is done the function which is contained in the functions.php called get_job_sts is called. Here is the code for that function.

* function to display bar chart for active jobs and CPU Usage
* @parms
* the connection to use

function get_job_sts(&$conn,$systyp) {
// get the number of jobs and the data to build the bars for

$desc = array(
array("Name" => 'NumEnt', "io" => I5_INOUT, "type" => I5_TYPE_INT),
array("DSName" =>"jobdet", "count" => 30, "DSParm" => array(
array("Name" => "jobname", "io" => I5_OUT, "type" => I5_TYPE_CHAR, "length" => "10"),
array("Name" => "jobuser", "io" => I5_OUT, "type" => I5_TYPE_CHAR, "length" => "10"),
array("Name" => "jobnumber", "io" => I5_OUT, "type" => I5_TYPE_CHAR, "length" => "6"),
array("Name" => "cpu", "io" => I5_OUT, "type" => I5_TYPE_INT))));
// prepare for the program call
$prog = i5_program_prepare("PHPTSTSRV(get_job_sts)", $desc, $conn);
if ($prog == FALSE) {
$errorTab = i5_error ();
echo "Program prepare failed <br>\n";
var_dump ( $errorTab );
die ();
// set up the input output parameters
$parameter = array("NumEnt" => 0);
$parmOut = array("NumEnt" => "nbr", "jobdet" => "jobdets");
$ret = i5_program_call($prog, $parameter, $parmOut);
if (!$ret) {
echo("<table cellspacing='0' cellpadding='0' summary='CPU Utilization for HA4i Jobs'>");
echo("<caption align=top>The current CPU Utilization for each HA4i Job on the " .$systyp ." System</caption>");
echo("<tr><th scope='col'>Job Name</th><th scope='col'>% CPU Unitlization</th></tr>");
for($i = 0; $i < $nbr; $i++) {
$cpu = $jobdets[$i]['cpu']/10;
if($i == 0) {
echo("<tr><td class='first' width='20px'>" .$jobdets[$i]['jobname'] ."</td><td class='value first'><img src='img/util.png' alt='' width='" .$cpu/2 ."%' height='16' />" .$cpu ."%</td></tr>");
elseif($i == ($nbr -1)) {
echo("<tr><td class='last' width='20px'>" .$jobdets[$i]['jobname'] ."</td><td class='value last'><img src='img/util.png' alt='' width='" .$cpu/2 ."%' height='16' />" .$cpu ."%</td></tr>");
else {
echo("<tr><td width='20px'>" .$jobdets[$i]['jobname'] ."</td><td class='value'><img src='img/util.png' alt='' width='" .$cpu/2 ."%' height='16' />" .$cpu ."%</td></tr>");
return 1;

The program call is prepared with a maximum of 30 job info structures, we would normally look to define this before the call and set the actual number of jobs to extract but for this instance we simply decided that 30 structures would be more than enough. After the program is called and the data returned we then build the table structure that will be used to display the data. We originally allowed the bar to take up all of the table width but after testing on our system which has uncapped CPU found that we would sometimes get over 100% CPU utilization. We still show the actual utilization but decided to halve the bar width which gave us a better display.

HA4i is running on our system in test so the CPU utilization is pretty infrequent even when we run a saturation test, but the image capture below will give you an idea of what the above code produces in our test environment.


CPU Ultization Bar Chart HA4i

Now we just need to include the relevant code into the HA4i/DR4i PHP interfaces and we will be able to provide more data via the dashboard which should help with managing the replication environment. You can see the original bar chart on which this example was produced here

Happy PHP’ing.