21
Sat, Dec
3 New Articles

The API Corner: Processing the QLOCALE System Value

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

Find out how to use internationalized IFS path names.

 

This is the fourth in a series of articles related to dynamically accessing and processing system values. In the first article, "In Search of System Values," we saw how the Retrieve Command Definition (QCDRCMDD) API could be used to access the list of valid system values for the release of the IBM i our program is running on. This list of valid system values was retrieved by using the IBM-provided Display System Value (DSPSYSVAL) command and by then accessing the list of special values associated with the SYSVAL keyword.

In the second article, "Accessing System Values," we saw how the Retrieve System Values (QWCRSVAL) API could be used to access the current values for each system value and how to display the current value for each of the system values, other than QLOCALE, using a subfile.

In the third article, "Performing CCSID Conversions Under Program Control," we reviewed the mechanics of using the Code Conversion Allocation (QtqIconvOpen), Code Conversion (iconv), and Code Conversion Deallocation (iconv_close) APIs to convert the XML UTF-8 output of the QCDRCMDD API to our job CCSID. This conversion was done to simplify the parsing of the SYSVAL keyword special values of the DSPSYSVAL command and to meet the input requirements of the QWCRSVAL API. In this article, we'll look at how to process the returned value of the QLOCALE system valuethe one system value we have not previously handled.

Most system values on the i are returned to you as simple fixed-length character strings, arrays of fixed-length character strings, or binary/integer values. The QLOCALE system value is an exception to this. The QLOCALE system value is returned as a data structure where subfields of the structure define various attributes of the QLOCALE path value. This returned structure is common to many system APIs that work with IFS path names, is documented here, and is provided in member QLG of source file QSYSINC/QRPGLESRC as the data structure QLGPN. The full structure is formatted as…

  • A 4-byte integer identifying the CCSID of the returned locale path name (with a value of 0 representing the current job default CCSID)
  • A 2-byte character field identifying the country or region ID associated with the returned locale path name (with a value of x'0000' representing the current job country of region ID)
  • A 3-byte character field identifying the language ID associated with the returned locale path name (with a value of x'000000' representing the current job language ID)
  • A 3-byte character field that is reserved (and is set to all x'00's)
  • A 4-byte integer indicating the type of locale path name returned. Possible returned values are 0the returned path value is a character string with path delimiters that are one character long, 1the returned path value is a pointer to a character string with path delimiters that are one character long, 2the returned path value is a character string with path delimiters that are two characters long, 3the returned path value is a pointer to a character string with path delimiters that are two characters long
  • A 4-byte integer providing the length of the locale path name in bytes
  • A 2-byte character field identifying the delimiter character used within the locale path name to separate elements of the path. This is most often the slash (/) character and is encoded in the same CCSID as the path
  • A 10-byte character field that is reserved (and is set to all x'00's)
  • Either a variable-length character string containing the path name or a pointer to a variable-length character string containing the path name

The QWCRSVAL API does not, however, use all of the capabilities of this structure. For instance, the QWCRSVAL API will return only the character string value of the QLOCALE path name, not a pointer to the path name. Other APIs, however, do use this pointer capability (which, among other things, helps avoid having to move potentially longand I mean really longpath names across different parameter interfaces).

On the other hand, the QWCRSVAL API also has unique requirements that cause the API to extend the use of some of these data structure subfieldsbeyond what is described above. The biggest requirement is the support of special values such as *NONE, *C, and *POSIX, which you won't find on most system API IFS path interfaces. In order to support the use of these special values, the QWCRSVAL API follows these rules:

  • Special values are always returned in the default CCSID of the job while non-special values (that is, "real" path names) are returned in a Unicode CCSID (13488 or 1200).
  • The special value *NONE is returned with a path length in bytes of 0.
  • The special values *C and *POSIX are returned with a path length in bytes of 1.
  • All real path names are returned with a path length greater than or equal to 2. This minimum value of 2 is due to all real path names being returned in Unicode where the encoding has a minimum of 2 bytes per character.

Implementing the above rules, here is an updated version of the LSTSYSVAL program that displays the first 60 bytes of the value of the QLOCALE system value (earlier versions simply displayed the text 'Not displayed').

h dftactgrp(*no)                                            

                                                            

fLstSVDspf cf   e             workstn sfile(SV_Sfl :RRNS1)  

                                                            

dRtvCmdD         pr                 extpgm('QCDRCMDD')    

d Cmd                           20a   const                  

d LenRcvVar                     10i 0 const                  

d DestFormat                     8a   const                  

d RcvVar                     65535a                          

d RcvVarFormat                   8a   const                  

d ErrCde                             likeds(QUSEC)          

                                                            

dConvertBuffer   pr                                        

                                                            

dDoLocale         pr                                        

                                                            

dmyHandler       pr           10i 0                      

d Controls                           likeds(HandlerInfo)  

d Event                         10i 0 value                

d StringPtr                       *   value                

d LenString                     20i 0 value                

d ExceptionID                   10i 0 value                

                                                            

dGetSysVals       pr                 extpgm('QWCRSVAL')  

d RcvVar                     65535a                        

d LenRcvVar                     10i 0 const                

d NbrSysVals                    10i 0 const                

d SysVals                       10a   dim(MaxSysVals)      

d ErrCde                             likeds(QUSEC)        

                                                          

dCmdD_Job         s         65527a                        

dRRNS1           s             4s 0                      

                                                          

dMaxSysVals       c                   const(300)          

dSysVals         s             10a   dim(MaxSysVals)      

                                                          

dCmdD_RcvVar     ds                 qualified            

d Ctl                                 likeds(QCDD0100)    

d CmdD_UTF8                 65527a                        

                                                         

dSysVal_RcvVar   ds         65535                        

d NbrSysValsRtn                 10i 0                      

                                                          

dSysValOfsPtr    s               *                        

dSysValOfs       s             10i 0 based(SysValOfsPtr)  

                                                          

dSVPtr           s               *                        

dSV               ds                qualified            

d                                     based(SVPtr)        

d Ctl                                 likeds(QWCRSVT)      

d CData                     10000a                            

d BData                         10i 0 overlay(CData :1)        

                                                              

dControls         ds                 likeds(HandlerInfo)      

dHandlerInfo     ds                 qualified based(NoPtr)  

d TopSysVal                    10i 0                          

d ParmFnd                         n                            

d KwdFnd                         n                            

d SysValFnd                       n                            

d SpcValFnd                      n                            

d ValueFnd                       n                            

d ValFnd                         n                            

                                                              

/copy qsysinc/qrpglesrc,qusec                                

/copy qsysinc/qrpglesrc,qcdrcmdd                              

/copy qsysinc/qrpglesrc,qwcrsval                              

                                                              

/free                                                          

                                                                

// Get command definition as a XML document. The document is  

// encoded in UTF8 (CCSID 1208).                              

                                                                

QUSBPrv = 0;                                                  

RtvCmdD('DSPSYSVAL QSYS' :%size(CmdD_RcvVar) :'DEST0100'      

         :CmdD_RcvVar :'CMDD0100' :QUSEC);                      

                                                                

// CmdD_UTF8 now contains the XML document in CCSID 1208.      

// The system values can be found in <Parm Kwd="SYSVAL" under  

// <SpcVal>. The first special value, for instance, is        

// <Value Val="QABNORMSW" MapTo="QABNORMSW"/>. The end of the  

// special values is, naturally, delimited by </SpcVal>.      

                                                                

// Convert command definition to job CCSID so you can "see"    

// the generated XML                                          

                                                              

ConvertBuffer();                                            

                                                                

// CmdD_Job now contains the XML document in the job CCSID.  

// Parse the XML document for SYSVAL special values          

                                                              

xml-sax %handler(myHandler :Controls) %xml(CmdD_Job);        

                                                              

if Controls.TopSysVal > 0;                                  

     // If any system values found then use QWCRSVAL to access

     // their current values                                  

                                                              

     GetSysVals(SysVal_RcvVar :%size(SysVal_RcvVar)            

               :Controls.TopSysVal :SysVals :QUSEC);          

                                                                

     *in32 = *on;                                              

     write SV_Ctl;                                            

     *in32 = *off;                                                

                                                                    

     SysValOfsPtr = %addr(SysVal_RcvVar) + %size(NbrSysValsRtn);  

     for RRNS1 = 1 to NbrSysValsRtn;                              

         SVPtr = %addr(SysVal_RcvVar) + SysValOfs;                

         SysValName = SV.Ctl.QWCSV;                                

         select;                                                  

           when SV.Ctl.QWCIS02 = 'L';                            

                 SVValue = '*LOCKED';                              

                                                                  

           when SysValName = 'QLOCALE';                          

                 DoLocale();                                      

                                                                  

           when SV.Ctl.QWCTD00 = 'C';                            

                 if SV.Ctl.QWCLD00 <= %size(SVValue);              

                   SVValue = %subst(SV.CData :1 :SV.Ctl.QWCLD00);

                 else;                                            

                   SVValue = %subst(SV.CData :1 :%size(SVValue));

                 endif;                                            

                                                                    

           when SV.Ctl.QWCTD00 = 'B';                            

                 SVValue = %editc(SV.BData :'X');                  

                                                                  

           other;                                                  

                 SVValue = '** PROBLEM **';                        

         endsl;                                                    

                                                                  

        write SV_Sfl;                                            

         SysValOfsPtr += 4;                                        

     endfor;                                                      

endif;                                                          

                                                                  

*in31 = (RRNS1 > 0);                                            

write SV_Keys;                                                  

dow (not *in03);                                                

     exfmt SV_Ctl;                                              

enddo;                                                          

                                                                  

*inlr = *on;                                                    

return;                                                        

                                                                  

/end-free                                                        

****************************************************************

pConvertBuffer   b                                              

dConvertBuffer   pi                                              

                                                                  

dIconvOpen       pr           52   extproc('QtqIconvOpen')    

d ToCode                       32   const                      

d FromCode                     32   const                      

                                                                  

dIconv           pr           10i 0 extproc('iconv')            

d iconv_t                       52   value                          

d InputPtr                       *                                  

d BytesToCvt                  10u 0                                

d OutputPtr                       *                                  

d BytesAvlForCvt               10u 0                                

                                                                      

dIConvClose       pr           10i 0 extproc('iconv_close')          

d iconv_t                       52   value                          

                                                                      

dInputPtr         s              *   inz(%addr(CmdD_RcvVar.CmdD_UTF8))

dOutputPtr       s               *   inz(%addr(CmdD_Job))            

dBytAvl_CmdD     s             10u 0 inz(%size(CmdD_Job))            

dRtnVal           s             10i 0                                  

                                                                      

dFromCode         ds                 qualified                      

d CCSID                         10i 0 inz(1208)                      

d ConvAlt                       10i 0 inz(0)                          

d SubstAlt                     10i 0 inz(0)          

d SSAlt                         10i 0 inz(0)          

d InpLenOpt                     10i 0 inz(0)          

d ErrOpt                       10i 0 inz(0)          

d                               8   inz(*ALLx'00')  

                                                      

dToCode           ds                 qualified      

d CCSID                         10i 0 inz(0)          

d ConvAlt                      10i 0 inz(0)          

d SubstAlt                     10i 0 inz(0)          

d SSAlt                         10i 0 inz(0)          

d InpLenOpt                     10i 0 inz(0)          

d ErrOpt                       10i 0 inz(0)          

d                               8   inz(*ALLx'00')  

                                                      

diconv_t         ds                                  

d                               10i 0 dim(13)        

                                                                

/free                                                          

                                                                

iconv_t = IconvOpen(ToCode :FromCode);                        

RtnVal = Iconv(iconv_t :InputPtr :CmdD_RcvVar.Ctl.QCDBRtn01    

                         :OutputPtr :BytAvl_CmdD);              

RtnVal = IconvClose(iconv_t);                                  

                                                                

/end-free                                                      

                                                                

pConvertBuffer   e                                              

****************************************************************

pmyHandler       b                                              

dmyHandler       pi           10i 0                            

d Controls                           likeds(HandlerInfo)        

d Event                         10i 0 value                      

d StringPtr                       *   value                      

d LenString                     20i 0 value                

d ExceptionID                   10i 0 value                

                                                            

dString           s         65535a   based(StringPtr)    

                                                          

/free                                                    

                                                          

select;                                                  

     when Event = *XML_START_DOCUMENT;                    

                                                          

         Controls.TopSysVal = 0;                          

         Controls.ParmFnd = *off;                        

         Controls.KwdFnd = *off;                          

         Controls.SpcValFnd = *off;                      

         Controls.ValueFnd = *off;                        

         Controls.ValFnd = *off;                          

                                                          

     when ((Event = *XML_START_ELEMENT) and              

           (%subst(String :1 :LenString)) = 'Parm');    

                                                        

         Controls.ParmFnd = *on;                        

                                                        

     when ((Event = *XML_ATTR_NAME) and                  

           (Controls.ParmFnd) and                        

          (%subst(String :1 :LenString)) = 'Kwd');      

                                                        

         Controls.KwdFnd = *on;                        

                                                        

     when ((Event = *XML_ATTR_CHARS) and                

           (Controls.KwdFnd));                          

                                                        

         if %subst(String :1 :LenString) = 'SYSVAL';    

             Controls.SysValFnd = *on;                    

         endif;                                        

         Controls.KwdFnd = *off;                            

                                                              

     when ((Event = *XML_START_ELEMENT) and                  

           (Controls.SysValFnd) and                          

           (%subst(String :1 :LenString)) = 'SpcVal');        

                                                              

         Controls.SpcValFnd = *on;                          

                                                              

     when ((Event = *XML_START_ELEMENT) and                  

           (Controls.SpcValFnd));                            

                                                              

         Controls.ValueFnd =                                

                   (%subst(String :1 :LenString) = 'Value');  

                                                              

     when ((Event = *XML_ATTR_NAME) and                      

           (Controls.ValueFnd));                              

                                                              

         Controls.ValFnd =                                  

                   (%subst(String :1 :LenString) = 'Val');    

                                                              

     when ((Event = *XML_ATTR_CHARS) and                      

           (Controls.ValFnd));                                

                                                              

         Controls.TopSysVal += 1;                            

         SysVals(Controls.TopSysVal) =                      

                 %subst(String :1 :LenString);              

         Controls.ValFnd = *off;                            

                                                              

     when ((Event = *XML_END_ELEMENT) and                    

           (Controls.SpcValFnd) and                          

           (%subst(String :1 :LenString) = 'Value'));        

                                                              

         Controls.ValueFnd = *off;                          

                                                              

     when ((Event = *XML_END_ELEMENT) and              

           (Controls.SysValFnd) and                    

           (%subst(String :1 :LenString)) = 'SpcVal');  

                                                        

         Controls.SpcValFnd = *off;                    

                                                        

     when ((Event = *XML_END_ELEMENT) and              

           (%subst(String :1 :LenString)) = 'Parm');    

                                                        

         Controls.SysValFnd = *off;                    

         Controls.ParmFnd = *off;                      

                                                        

     other;                                            

         // Ignore                                    

endsl;                                                

                                                        

return 0;                                            

                                                                

/end-free                                                      

                                                                

pmyHandler       e                                              

****************************************************************

pDoLocale        b                                              

dDoLocale         pi                                            

                                                                

dIconvOpen       pr           52   extproc('QtqIconvOpen')    

d ToCode                       32   const                      

d FromCode                     32   const                      

                                                                

dIconv           pr           10i 0 extproc('iconv')            

d iconv_t                       52   value                      

d InputPtr                       *                              

d BytesToCvt                   10u 0                            

d OutputPtr                       *                              

d BytesAvlForCvt               10u 0                            

                                                                

dIConvClose       pr           10i 0 extproc('iconv_close')    

d iconv_t                     52   value                      

                                                                

dInputPtr         s               *                              

dOutputPtr       s               *   inz(%addr(SVValue))        

dBytesToCvt       s             10u 0                            

dBytAvl_Path     s             10u 0 inz(%size(SVValue))        

dRtnVal           s             10i 0                            

                                                                

dFromCode         ds                 qualified                  

d CCSID                         10i 0                            

d ConvAlt                       10i 0 inz(0)                    

d SubstAlt                     10i 0 inz(0)                    

d SSAlt                         10i 0 inz(0)                    

d InpLenOpt                     10i 0 inz(0)                    

d ErrOpt                       10i 0 inz(0)            

d                               8   inz(*ALLx'00')    

                                                      

dToCode           ds                 qualified        

d CCSID                         10i 0 inz(0)            

d ConvAlt                       10i 0 inz(0)            

d SubstAlt                      10i 0 inz(0)            

d SSAlt                         10i 0 inz(0)            

d InpLenOpt                     10i 0 inz(0)            

d ErrOpt                       10i 0 inz(0)            

d                               8   inz(*ALLx'00')    

                                                        

diconv_t         ds                                    

d                               10i 0 dim(13)          

                                                        

dPathDSPtr        s               *                    

dPathDS           ds                 qualified        

d                                     based(PathDSPtr)    

d Hdr                                 likeds(QLGPN)      

d Path                       2048a                      

                                                          

/copy qsysinc/qrpglesrc,qlg                              

                                                          

/free                                                    

                                                          

PathDSPtr = %addr(SV.CData);                            

                                                          

if ((PathDS.Hdr.QLGPL = 0) or                          

     (PathDS.Hdr.QLGPL = 1));                            

     SVValue = PathDS.Path;                              

else;                                                  

     FromCode.CCSID = PathDS.Hdr.QLGCCSID02;              

     iconv_t = IconvOpen(ToCode :FromCode);              

                                                          

     InputPtr = %addr(PathDS.Path);                    

     BytesToCvt = PathDS.Hdr.QLGPL;                    

     SVValue = *blanks;                                

     RtnVal = Iconv(iconv_t :InputPtr :BytesToCvt      

                           :OutputPtr :BytAvl_Path);  

                                                      

     RtnVal = IconvClose(iconv_t);                    

endif;                                              

                                                      

/end-free                                            

                                                      

pDoLocale         e                                    

The changes from last month are the…

  • addition of a prototype for subprocedure DoLocale()
  • change in processing when the QLOCALE system value is encountered. Previously, LSTSYSVAL displayed the text 'Not displayed' while now the subprocedure DoLocale() is run
  • addition of subprocedure DoLocale()

Assuming that the source shown previously is stored in member LSTSYSVAL of source file QRPGLESRC, you can create the program using the command CRTBNDRPG PGM(LSTSYSVAL). To run the program, use the command CALL PGM(LSTSYSVAL).

Subprocedure DoLocale() duplicates many prototype and local variables of subprocedure ConvertBuffer(). This is done so that we can concentrate on the actual processing of DoLocale() and does not imply that I would really implement LSTSYSVAL with all of this duplication.

The processing within DoLocale() is straightforward enough. As an instance of the QSYSINC-provided QLGPN structure is defined as PathDS and based on the pointer PathDSPtr, the first thing done in DoLocale is the setting of PathDSPtr to the address of the system value locale information returned by QWCRSVAL. With addressability to the structure established, DoLocale() checks to see if the length of the returned path is 0 or 1. If so, then a special value has been specified for the QLOCALE system value and this special value is copied to the subfile field SVValue for display. If the length of the returned path is not 0 or 1, then DoLocale() performs a CCSID conversion of the returned path name. This CCSID conversion is done using the same APIs that were discussed last month in the article "Performing CCSID Conversions Under Program Control."

The differences between last month's discussion of ConvertBuffer() and this month's DoLocale() are…

  • The CCSID to convert from (FromCode.CCSID) is set to the Unicode CCSID value returned by the QWCRSVAL API (PathDS.Hdr.QLGCCSID02).
  • The variable InputPtr is set to the address of the returned Unicode-encoded path (PathDS.Path).
  • The number of bytes to convert is set to the length of the returned Unicode-encoded path (PathDS.Hdr.QLGPL).
  • The variable OutputPtr is set to the address of the subfile field SVValue (SVValue being used to display system value values).
  • The number of bytes available for the CCSID converted path data, BytAvl_Path, is set to the size of the SVValue subfile field.

As I know that LSTSYSVAL (as currently implemented) will be displaying only the first 60 bytes of the iconv() converted QLOCALE path, DoLocale() is taking advantage of a feature of the iconv() API. The feature is that the iconv() API will return only that number of full characters that will fit in the number of bytes available for converted data (BytAvl_Path). So if the number of bytes available for the CCSID converted path is 60, and the actual length of the converted path is, say, 100 bytes, then iconv() will stop after writing the first 60 bytes to SVValue, which is exactly what we want. If the actual length of the converted path is less than 60 bytes, then iconv() will write only the actual number of converted bytes to SVValue, which is again exactly what we want (as DoLocale() previously set SVValue to blanks, so there is no concern about residual values from previous system value values).

If we did want LSTSYSVAL to display the full QLOCALE path value, as opposed to only the first 60 bytes, then we could take one of two approaches. One method would be to convert the QWCRSVAL returned path into a buffer sufficiently large to hold all converted data and then write a subfile record for the first 60 bytes, a subfile record for the next 60 bytes, and so on. A second approach would be to have iconv() iteratively return 60 bytes of converted data where the first iteration returns the fist 60 bytes, the second iteration the next 60 bytes, and so on (with each iteration writing one subfile record).

In a future article, we'll look at how to have the iconv() API restart a data conversion within a buffer of data to be converted. Following the current discussion, that would be starting the conversion at the first byte of PathDS.Path, restarting the conversion at the input byte of PathDS.Path associated with the 61st converted byte, restarting the conversion at the input byte of PathDS.Path associated with the 121st converted byte, and so on.

As usual, if you have any API questions, send them to me at This email address is being protected from spambots. You need JavaScript enabled to view it.. I'll see what I can do about answering your burning questions in future columns.

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

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: