Wed, Jul
0 New Articles

Use the MI to Work with Pointers in ILE RPG

  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

If you've been avoiding this technique, maybe you shouldn't be.


With the introduction of the ILE programming model, high-level languages (HLLs), including RPG, are enabled to make bound calls (procedure calls). This makes it possible for programs written in ILE RPG to cooperate with all the other HLLs available on the i5/OS, including Java, and to reuse all existing algorithms and functionalities that have been implemented in other HLLs. This fact is often regarded as proof of the RPG language's openness and modernization.


At the same time, the i5/OS machine interface (MI) layer exposed invocation interfaces to ILE programs, which are referred to as "bound program access interfaces" in IBM's MI documentation and as "system built-ins" in IBM's ILE RPG documentation. Now, programs written in RPG as well as in other i5/OS HLLs can interact with the operating system at the lowest level, the MI layer. This enables RPG programs to reuse the most efficient algorithms provided by the MI layer and to access system objects (MI objects) directly. This makes the RPG programming language more powerful.

Overview of MI Pointers

We know that the i5/OS is an object-based operating system. As the well-known UNIX idiom says, everything in a UNIX system is a file; on i5/OS, everything is an object. And the only way we can refer to an i5/OS object (MI object) or data in the object is through the MI pointer. For example:


  • A system pointer (SYSPTR) addresses to an MI object. Each MI instruction that accesses a specific type of MI object expects a system pointer as a necessary operand to identify which MI object to deal with.
  • A space pointer (SPCPTR) is used to address bytes within a space object. SPCPTR is the pointer type used in both MI and HLLs to address stack, static, and heap storage.
  • A data pointer (DTAPTR) is a special type of space pointer that also stores the attributes, date type, and length of the data addressed by the pointer.


Also, MI pointers represent other objects in a program or in a process in run time, such as procedure pointers, instruction pointers, invocation pointers, and so on.


Then, how does one represent an MI pointer in an RPG program?  Actually, the bound program access interfaces exposed to ILE HLLs by the MI layer do not distinguish different MI pointer types, and all 16-byte pointer types in ILE RPG and other ILE HLLs can be used in MI instruction invocations. Thus, all MI pointers can be represented by an RPG variable of pointer type (with data type field set to character '*' in position 40 in the definition specification). Note that when representing a procedure pointer with an RPG pointer variable that is to be used as the operand of RPG operation code CALLB (Call a Bound Procedure), we must qualify the pointer variable with the PROCPTR definition-specification keyword; otherwise, the RPG compiler will cause the RNF7607 exception (The field on the C specification is not a procedure pointer.).


Let's go through some of the most often used pointer operations.

Pointer Operations Supported by ILE RPG

As an HLL supporting pointers, ILE RPG provides the following support for pointer operations:


  • Testing for NULL pointers. To test whether a pointer is a NULL pointer, compare it to the reserved word *NULL of the ILE RPG language. For example:


     d p               s               *

     d pp              s               *   procptr




           if p = *null and pp = *null;

               dsply 'null' '';



           *inlr = *on;



  • Retrieving a space pointer that addresses the leftmost byte of an RPG variable by built-in %addr().
  • Changing the offset of a space pointer. To change the offset of a space pointer, use operator +, -, +=, or -=. For example:

     d buf             ds                  qualified

     d     fa                         4a   inz('FLDA')

     d     fb                         4a   inz('FLDB')

     d     fc                         4a   inz('FLDC')


     d ptr             s               *

     d var             ds             4    based(ptr)




           ptr = %addr(buf.fb); // point ptr to buf.fb

           dsply 'var' '' var;  // 'FLDB'


           ptr = ptr + 4;       // offset ptr forward 4 bytes

           dsply 'var' '' var;  // 'FLDC'


           ptr -= 8;            // offset ptr backward 8 bytes

           dsply 'var' '' var;  // 'FLDA'


           *inlr = *on;



  • Copying a pointer. By using either operation code EVAL or operation code MOVE, an ILE RPG program can copy a pointer from one storage location to another, whether copying a pointer directly or copying a data structure containing a pointer. Note that it is not always the same when copying pointers at the MI layer. As we know, an i5/OS pointer is tagged protected, and not all storage copy MI instructions reserve the usability of a duplicated pointer.
  • Retrieving a procedure pointer that addresses a procedure. To retrieve a procedure pointer that addresses a procedure, use ILE RPG built-in %paddr().
  • Calling a procedure by a procedure pointer with operation code CALLB. Here is an example.


     h dftactgrp(*no)


     d increase        pr

     d     number                    10i 0


     d pptr            s               *   procptr

     d n               s             10i 0 inz(95)


      * retrieve a procedure pointer

     c                   eval      pptr = %paddr(increase)


      * call procedure increase by PROCPTR

     c                   callb     pptr

     c                   parm                    n


     c     'result'      dsply                   n

     c                   seton                                          lr


     p increase        b


     d increase        pi

     d     number                    10i 0



           number += 1;



     p increase        e


Operating Pointers with MI Instructions

The prerequisite to invoke an MI instruction is to declare the right prototype for it. It is quite time-consuming to declare and validate prototypes for all the more than 200 MI instructions that have bound program access interfaces. System-builtin Headers for ILE RPG, a sub-project of the open-source project i5/OS Programmer's Toolkit, is working on this task. Prototypes of MI instructions mentioned in the following examples are extracted from one of the header files of the project, SourceForge's mih52.rpgleinc.


Determining the Type of a Pointer


To make sure that a pointer is of an expected type, use MI instruction Compare Pointer Type (CMPPTRT). To find out the type of a pointer, use MI instruction Materialize Pointer (MATPTR).


The prototype of MI instruction CMPPTRT provided by mih52.rpgleinc is shown as the following:


     /* returns 1 if ptr is of specified type, otherwise 0. */

     d cmpptrt         pr            10i 0 extproc('_CMPPTRT')

      * expected pointer type

     d     ptr_type                   1a   value

      * pointer to check

     d     ptr                         *   value


In the following example ILE RPG program, CMPPTRT is used to test whether a given pointer is a system pointer.


      /copy mih52


     d ptr             s               *

     d r               s             10i 0




           // locate a program object

           rslvsp_tmpl.obj_type = x'0201';

           rslvsp_tmpl.obj_name = 'P03';


           rslvsp2(ptr : rslvsp_tmpl);


           if cmpptrt(x'01' : ptr) = 1;

               // ptr is a SYSPTR



           *inlr = *on;



This is the prototype of MI instruction MATPTR.


     /* MATPTR, materialize pointer attributes */

     d matptr          pr                  extproc('_MATPTR')

     d     receiver                    *   value

     d     ptr                         *

     /* MATPTR template header */

     d matptr_tmpl_t   ds                  qualified

     d                                     based(dummy_ptr)

      * bytes provided

     d     bytes_in                  10i 0

      * bytes available

     d     bytes_out                 10i 0

      * pointer type returned

     d     ptr_type                   1a


This example ILE RPG program uses MI instruction MATPTR to get the type of a pointer:


      /copy mih52


     d type            s             30a

     d ptr             s               *   inz(%addr(type))


     d tmpl_ptr        s               *

     d tmpl            ds                  likeds(matptr_tmpl_t)

     d                                     based(tmpl_ptr)




           // allocate storage for MATPTR template header

           tmpl_ptr = modasa(9);

           tmpl.bytes_in = 9;


           matptr(tmpl_ptr : ptr);


           // check ptr_type


           when tmpl.ptr_type = x'01';

               type = 'System pointer';

           when tmpl.ptr_type = x'02';

               type = 'Space pointer';

           // more pointer types

           when tmpl.ptr_type = x'FF';

               type = 'Unsupported pointer';

           other; // ...



           dsply 'pointer type' '' type;


           *inlr = *on;



Retrieving Attributes of a Pointer


To retrieve attributes of a pointer, use MI instruction MATPTR. Here is an example of retrieving attributes of a procedure pointer (PROCPTR):


Attributes of a Procedure Pointer


Data Type




Number of bytes provided for materialization



Number of bytes available for materialization



Pointer type

Hex 01 = System pointer

Hex 02 = Space pointer

Hex 03 = Data pointer

Hex 04 = Instruction pointer

Hex 05 = Invocation pointer

Hex 06 = Procedure pointer

Hex 07 = Label pointer

Hex 08 = Suspend pointer

Hex 09 = Synchronization pointer

Hex FF = Unsupported pointer

Note: For a PROCPTR, this field is always x'06'.



Pointer status

Bit 0 = 1 if process object no longer exists.

Bit 1 = 1 if pointer is from another process.

Bit 2 = 1 if referenced program cannot be accessed.

Bit 3 = 1 if containing process owns a shared activation group

Bit 4-7, reserved.






Module number. Index in the module list of the bound program (*PGM or *SRVPGM) for the module whose activation the pointer addresses.



Procedure number. Index in the procedure list of the module for the procedure addressed by the pointer.



Activation mark. The activation mark of the activation that contains the activated procedure. Zero if the program activation no longer exists.



An activation group mark of the activation group that contains the activated procedure. Zero if the program activation no longer exists.



Containing program. A system pointer to the program object (*PGM or *SRVPGM) that contains the procedure. Null if the program activation no longer exists.



Containing process. A system pointer to the process control space object (*PCS) that contains the procedure's activation group. A null pointer value is returned if the process control space object no longer exists or if it is no longer possible to determine the containing process for a destroyed activation group.



8-byte activation mark.



8-byte activation group mark.


-- End --



The following shows the procedure pointer information structure declared in mih52.rpglinc.


     /* length of PROCPTR information */

     d matptr_procptr_info_length...

     d                 c                   80


     /* PROCPTR info structure */

     d matptr_procptr_info_t...

     d                 ds                  qualified

     d                                     based(dummy_ptr)

     d     bytes_in                  10i 0

     d     bytes_out                 10i 0

     d     ptr_type                   1a

     d     ptr_status                 1a

     d                                6a

     d     mod_num                   10u 0

     d     proc_num                  10u 0

     d     act_mark                  10u 0

     d     ag_mark                   10u 0

     d     pgm                         *

     d     process                     *

     d     act_mark2                  8a

     d     ag_mark2                   8a


The following ILE RPG program T030 accepts a procedure pointer as its only input parameter and retrieves attributes of the given procedure pointer.



      * @file t030.rpgle


      * Materialize a PROCPTR



      /copy mih52


     d i_main          pr                  extpgm('T030')

     d     pptr                        *


     d info_ptr        s               *

     d info            ds                  likeds(matptr_procptr_info_t)

     d                                     based(info_ptr)


     d sysptr_info_ptr s               *

     d sysptr_info     ds                  likeds(matptr_procptr_info_t)

     d                                     based(info_ptr)


     d i_main          pi

     d     pptr                        *




           // allocate storage for MATPTR template

           info_ptr = modasa(matptr_procptr_info_length);

           info.bytes_in = matptr_procptr_info_length;


           // materialize input PROCPTR

           matptr(info_ptr : pptr);


           // check returned PROCPTR attributes

           dsply 'module number' '' info.mod_num;

           dsply 'procedure number' '' info.proc_num;


           sysptr_info_ptr = modasa(matptr_sysptr_info_length);

           sysptr_info.bytes_in = matptr_sysptr_info_length;


           // retrieve containing program's name and library

           matptr(sysptr_info_ptr : info.pgm);

           dsply 'program name' '' sysptr_info.obj_name;

           dsply 'library name' '' sysptr_info.ctx_name;


           // AG mark:       info.ag_mark

           // ... ...


           *inlr = *on;



Another ILE RPG program, T029, calls program T030 twice, passing respectively a procedure pointer addressing procedure increase() in T029's program entry point (PEP) module and a procedure pointer addressing the C library routine printf().



      * @file t029.rpgle


      * test of matptr()


      * call program T030.



     h dftactgrp(*no)

     h bnddir('QC2LE')


     d t030            pr                  extpgm('T030')

     d     ppp                         *   procptr


     d increase        pr

     d     num                       10i 0


     d ptr             s               *   procptr




           ptr = %paddr(increase);



           // call T030 with procptr addressing

           // libc procedure printf()

           ptr = %paddr('printf');



           *inlr = *on;



     p increase        b

     d increase        pi

     d     num                       10i 0


     c                   eval      num = num + 1

     c                   return


     p increase        e


You can see that procedure increase() is the first procedure of the first module of program T029, and the C library routine printf() is the fifth procedure of service program QC2IO's thirteenth module.


DSPLY  module number             1  


DSPLY  procedure number             1


DSPLY  program name    T029          


DSPLY  library name    LSBIN        


DSPLY  module number            13  


DSPLY  procedure number             5


DSPLY  program name    QC2IO        


DSPLY  library name    QSYS         


Managing i5/OS Objects by Using System Pointers


One can access an i5/OS object only by using a system pointer address to the object. A system pointer to an i5/OS object is somewhat like a ticket by which you are permitted to get on a train and find your seat. To invoke an object-related MI instruction on an i5/OS object, you must show such a ticket. Here are a couple of practical examples of accessing i5/OS objects by system pointers.


Exchange Data via a User Queue Object


A queue object (with object type code hex 0A) is the native interprocess communication (IPC) mechanism on i5/OS. The most well-known of all types of i5/OS queue objects is Data Queue (*DTAQ). Another widely used type of i5/OS queue object is User Queue (*USRQ), which can be regarded as a lightweight but more powerful *DTAQ. Want to know other types of i5/OS queue objects?  Issue the following CL command on your machine and search for objects with type code hex 0A in the resulting spooled file.


DMPSYSOBJ OBJ(*PCS)   /* the process control object of your current job */

          TYPE(0A)   /* object type of queue objects */


Here is an example of exchanging data via a user queue object. First, we create a user queue object by calling API QUSCRTUQ. Next, we put a queue entry onto the created user queue object by using MI instruction ENQ. Last, we dequeue a queue entry from the user queue object by using MI instruction DEQ.



This CL command creates a user queue with name QPROC:



     'QPROC     LSBIN'    /* user queue name */

     'PROCPTR'            /* extended attribute */

     'F'                  /* queue type: FIFO, first in first out */

     X'00000000'          /* key length = 0 */

     X'00000010'          /* message size = 16 */

     X'00000020'          /* initial number of messages = 32 */

     X'00000020'          /* number of messages of each extension = 32 */

     '*CHANGE'            /* public authority */

     'PROCPTR holder'     /* text description */

     '*YES'               /* replace */

     X'00000010000000000000000000000000'  /* API error code */

     '*DEFAULT'           /* object domain */

     '*YES'               /* permit queue entries to contain pointers */



Here are the prototypes of MI instructions ENQ and DEQ:


     /* message prefix used by instruction ENQ */

     d enq_prefix_t    ds                  qualified

     d     msg_len                   10i 0

      * for keyed queue objects

     d     msg_key                  256a


     /* enqueue to a queue object */

     d enq             pr                  extproc('_ENQ')

     d     queue                       *

     d     msg_prefix                  *   value

     d     msg                         *   value


     /* message prefix used by instruction DEQ */

     d deq_prefix_t    ds                  qualified

     d     deq_time                   8a

     d     time_out                   8a

     d     msg_len                   10i 0

     d     state_flag                 1a

      * for keyed queue objects; input key, output key

     d     msg_keys                 512a


     /* dequeue from a queue object without waiting */

     d deqi            pr            10i 0 extproc('_DEQI')

     d     msg_prefix                  *   value

     d     msg                         *   value

     d     queue                       *


     /* dequeue from or wait on a queue object */

     d deqwait         pr                  extproc('_DEQWAIT')

     d     msg_prefix                  *   value

     d     msg                         *   value

     d     queue                       *


ILE RPG program T025 enqueues an entry into user queue QPROC:


      /copy mih52


     d q               s               *

     d prefix          ds                  likeds(enq_prefix_t)


      * make sure the message text operand is aligned to

      * 16 bytes boundary when the target queue object

      * can contain pointers in queue entries.


     d text            s             16a   inz('Hello')




           // resolve target *USRQ QPROC

           rslvsp_tmpl.obj_type = x'0A02';

           rslvsp_tmpl.obj_name = 'QPROC';

           rslvsp2(q : rslvsp_tmpl);


           // enqueue *USRQ QPROC

           prefix.msg_len = 8;

           enq( q : %addr(prefix) : %addr(text) );


           // use CL command DSPQMSG to check *USRQ QPROC

           // e.g. DSPQMSG QPROC *USRQ


           *inlr = *on;



ILE RPG program T026 dequeues an entry from user queue QPROC:


      /copy mih52


     d q               s               *

     d prefix          ds                  likeds(deq_prefix_t)


      * make sure the message text operand is aligned to

      * 16 bytes boundary when the target queue object

      * can contain pointers in queue entries.


     d text            s             16a   inz(*all'-')

     d rtn             s             10i 0




           // resolve target *USRQ QPROC

           rslvsp_tmpl.obj_type = x'0A02';

           rslvsp_tmpl.obj_name = 'QPROC';

           rslvsp2(q : rslvsp_tmpl);


           // dequeue *USRQ QPROC

           prefix.msg_len = 16;

           rtn = deqi( %addr(prefix) : %addr(text) : q );


           if rtn = 1;

               dsply 'Q entry' '' text;


               dsply 'nothing DEQed' '';



           *inlr = *on;



Get All User Profiles of Your i5/OS Installation


Everything on i5/OS is an object. A user profile object (*USRPRF) is of object type hex 08 and sub-type code 01. Theoretically, we can retrieve all objects residing in a library (a context object in the MI layer) with the MI instruction Materialize Context (MATCTX). Here is an example of retrieving *USRPRF objects by MI instruction MATCTX.


This is the prototype of one of MATCTX's bound access interfaces, _MATCTX1:


     /* MATCTX option structure */

     d matctx_option_t...

     d                 ds            46    qualified

     d     sel_flag                   1a                                        selection flag

     d     sel_criteria...

     d                                1a                                        selection criteria

     d     name_len                   5i 0                                      selection name length

     d     obj_type                   1a                                        object type code

     d     obj_subtype...

     d                                1a                                        object sub-type code

     d     name                      30a                                        object name

     d     timestamp...

     d                                8a                                        selection timestamp

     d     asp_num                    2a                                        independent ASP number


     /* length of MATCTX option structure */

     d matctx_option_length...

     d                 c                   46


     /* MATCTX template */

     d matctx_receiver1_t...

     d                 ds                  qualified

     d     bytes_in                  10i 0                                      bytes provided

     d     bytes_out                 10i 0                                      bytes available

     d     ctx_type                   2a                                        context type/sub-type

     d     ctx_name                  30a                                        context name

     d     ctx_opt                    4a                                        context options

     d     rcvy_opt                   4a                                        recovery options

     d     spc_size                  10i 0                                      space size

     d     spc_init_val...

     d                                1a                                        initial value of space

     d     perf_cls                   4a                                        performance class

     d                               23a                                        reserved

     d     acc_grp                     *                                        access group


     d matctx_offset1...

     d                 c                   96


     /* MATCTX, materialize context */

     d matctx1         pr                  extproc('_MATCTX1')

     d     receiver                    *   value

     d     option                    46a


ILE RPG program T031 lists all user profiles of an i5/OS installation:



      * @file t031.rpgle


      * test of MATCTX.

      * retrieve *USRPRFs from the machine context (of system ASP)



      /copy mih52


      * SPCPTR to receiver

     d rcv_ptr         s               *

     d rcv_info        ds                  likeds(matctx_receiver1_t)

     d                                     based(rcv_ptr)


     d obj_info        ds                  qualified

     d                                     based(rcv_ptr)

     d     type                       2a

     d     name                      30a


     d option          ds                  likeds(matctx_option_t)

     d BUF_LEN         c                   x'010000'

     d num             s             10i 0

     d ind             s             10i 0




           propb(%addr(option) : x'00' : matctx_option_length);


           // receive object's symbol identifications

           option.sel_flag = x'05';

           // select by object's type code

           option.sel_criteria = x'01';

           // type code of a *USRPRF object is x'08'

           option.obj_type = x'08';


           // allocate storage for receiver

           rcv_ptr = modasa(BUF_LEN);       // 1Mb

           rcv_info.bytes_in = BUF_LEN;


           // materialize the machine context for *USRPRFs

           matctx1 (rcv_ptr : option);


           // display returned *USRPRFs

           num = (rcv_info.bytes_out - matctx_offset1) / %size(obj_info);

           rcv_ptr += matctx_offset1;


           for ind = 1 to num;

               dsply 'user profile' '' obj_info.name;

               rcv_ptr += %size(obj_info);



           *inlr = *on;




When talking about using MI instructions in RPG programs, some of us might argue that it will affect code consistency and require extra training and maintenance. In my opinion, it is just a matter of viewpoint. For example, if you like to use routines in other i5/OS HLLs, such as C in memory operations or mathematical calculations, you should be aware that memory operation MI instructions and mathematical MI instructions provide the same functionality as their C library counterparts but without dependency on the C library's service programs, such as QC2UTIL2, and will then shorten the time required by an ILE RPG program's activation progress. Or if you consider RPG as the only native language on the platform, then you should also know that, starting with S/38, the platform has been speaking in the MI language to all of us.



Junlei Li

Junlei Li is a programmer from Tianjin, China, with 10 years of experience in software design and programming. Junlei Li began programming under i5/OS (formerly known as AS/400, iSeries) in late 2005. He is familiar with most programming languages available on i5/OS—from special-purpose languages such as OPM/ILE RPG to CL to general-purpose languages such as C, C++, Java; from strong-typed languages to script languages such as QShell and REXX. One of his favorite programming languages on i5/OS is machine interface (MI) instructions, through which one can discover some of the internal behaviors of i5/OS and some of the highlights of i5/OS in terms of operating system design.


Junlei Li's Web site is http://i5toolkit.sourceforge.net/, where his open-source project i5/OS Programmer's Toolkit (https://sourceforge.net/projects/i5toolkit/) is documented.



Support MC Press Online


Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: