Menu Documentation Tool

For many applications, the first line of security is the menu system. A user is given an initial menu, and is only allowed to execute programs called from that menu, or menus referenced by the initial menu. The question is, then, what programs are reachable from a given initial menu?

Provided are:

The program is called from the command line with the following parameters:

The prune program parameter controls whether all occurences of a program are printed, or only the one with the shortest path.



As an example, consider the folowing menus

                           -------------------------
                           |        Menu A         |
                           |                       |
                           |1. Menu AA  12. PGM01  |
                           |2. Menu AB             |
                           |3. Menu AC             |
                           |                       |
                           |                       |
                           -------------------------
-------------------------  -------------------------  -------------------------
|        Menu AA        |  |        Menu AB        |  |        Menu AC        |
|                       |  |                       |  |                       |
|1. Menu AAA 12. PGM01  |  |1. Menu ABA 12. PGM02  |  |            11. PGM01  |
|2. Menu AAB 13. PGM02  |  |2. Menu ABB 13. PGM03  |  |            12. PGM02  |
|                       |  |                       |  |            13. PGM03  |
|                       |  |                       |  |            14. PGM04  |
|                       |  |                       |  |                       |
-------------------------  -------------------------  -------------------------
-------------------------  -------------------------
|        Menu AAA       |  |        Menu AAB       |
|                       |  |                       |
|            12. PGM01  |  |            12. PGM06  |
|            13. PGM02  |  |            13. PGM07  |
|            14. PGM05  |  |            14. PGM08  |
|                       |  |                       |
|                       |  |                       |
-------------------------  -------------------------
-------------------------  -------------------------
|        Menu ABA       |  |        Menu ABB       |
|                       |  |                       |
|            12. PGM07  |  |            12. PGM09  |
|            13. PGM08  |  |            13. PGM10  |
|            14. PGM09  |  |            14. PGM11  |
|                       |  |                       |
|                       |  |                       |
-------------------------  -------------------------
Now, the way these menus are represented in the database is:
 
AAMENU      AAOPTION  AAOBJECT    AAOBJECTYP                 
------      --------  --------    ----------  
 A               1     AA              M                      
 A               2     AB              M                      
 A               3     AC              M                      
 A              12     PGM01           P                      
 AA              1     AAA             M                      
 AA              2     AAB             M                      
 AA             12     PGM01           P                      
 AA             13     PGM02           P                      
 AAA            12     PGM01           P                      
 AAA            13     PGM02           P                      
 AAA            14     PGM05           P                      
 AAB            12     PGM06           P                      
 AAB            13     PGM07           P                      
 AAB            14     PGM08           P                      
 AB              1     ABA             M                      
 AB              2     ABB             M
 AB             12     PGM02           P             
 AB             13     PGM03           P             
 ABA            12     PGM07           P             
 ABA            13     PGM08           P             
 ABA            14     PGM09           P             
 ABB            12     PGM09           P             
 ABB            13     PGM10           P             
 ABB            14     PGM11           P             
 AC             12     PGM01           P             
 AC             13     PGM02           P             
 AC             14     PGM03           P             
 AC             15     PGM04           P             

To run the program in unpruned (plum) mode:

 call cp1220r (A '0')

giving the following result:

 PGM01/12 AA/ 1 A                            
 PGM01/12 AAA/ 1 AA/ 1 A                     
 PGM01/12 AC/ 3 A                            
 PGM01/12 A                                  
 PGM02/12 AB/ 2 A                            
 PGM02/13 AA/ 1 A                            
 PGM02/13 AAA/ 1 AA/ 1 A                     
 PGM02/13 AC/ 3 A                            
 PGM03/13 AB/ 2 A                            
 PGM03/14 AC/ 3 A                            
 PGM04/15 AC/ 3 A                            
 PGM05/14 AAA/ 1 AA/ 1 A                     
 PGM06/12 AAB/ 2 AA/ 1 A                     
 PGM07/12 ABA/ 1 AB/ 2 A                     
 PGM07/13 AAB/ 2 AA/ 1 A                     
 PGM08/13 ABA/ 1 AB/ 2 A                     
 PGM08/14 AAB/ 2 AA/ 1 A           
 PGM09/12 ABB/ 2 AB/ 2 A           
 PGM09/14 ABA/ 1 AB/ 2 A           
 PGM10/13 ABB/ 2 AB/ 2 A           
 PGM11/14 ABB/ 2 AB/ 2 A           

Pretty ugly. This was orginally written as part of an application to programmatically maintain the JDEdwards Function Key Security file (F9612). Not only were all program calls from menus documented, but also program calls from other programs (via function keys and selection exits). Once we determined which programs were reachable from the initial menu, we went into each program and turned off each function key/selection option which referenced a program which was *not* reachable from the initial menu. Pretty reports were not part of the product, but this is beta free-ware, so feel free to write your own.


This is also probably more information than we need. More useful is the listing produced in prune mode, which shows only the shortest path to each program.

To run the program in prune mode:

call cp1220r (A '1')

giving the following result

 PGM01/12 A                             
 PGM02/13 AA/ 1 A                       
 PGM03/13 AB/ 2 A                       
 PGM04/15 AC/ 3 A                       
 PGM05/14 AAA/ 1 AA/ 1 A                
 PGM06/12 AAB/ 2 AA/ 1 A                
 PGM07/13 AAB/ 2 AA/ 1 A                
 PGM08/14 AAB/ 2 AA/ 1 A                
 PGM09/14 ABA/ 1 AB/ 2 A                
 PGM10/13 ABB/ 2 AB/ 2 A                
 PGM11/14 ABB/ 2 AB/ 2 A                

The following links take you to the source code, written in beautiful /free ILE/RPG. The source is distributed under a creative commons license.

cp1220f.txt - flat file (interface)
cp1220r.txt - Menu Documentation Tool
cp1221r.txt - File Conversion Tool (f00821 => cp1220f
cp1222r.txt - Debug Tool (print heap)


How it works

Why, with dynamic data structures. I create a linked list in the heap, and store the pointers to my heap storage in a user space. The following is an example of how we determine whether a given menu already exists in the linked list (transitive references to menus lead to infinite loops)


The data structure looks like ...

 *                                                                     
 * used for records in heap storage                                    
 *                                                                     
d recordDS        ds                  Based(ds@)                       
d  parent@                        *                                    
d  option                        3a                                    
d  object                       10a                                    
d  pathLen                      10i 0                                  
d  pathVar                       1a                                    
 *      

... and pruneMnu() utilizes the data structure thusly:

 ppruneMnu         b                                                     
 d                 pi             1n                                     
 d testMenu                      10a                                     
 d pmDS            ds                  LikeDS(recordDS) Based(pm@)       
  /free                                                                  
   pm@ = ds@;                                                            
   DoW (pmDS.parent@ <> *NULL And pmDS.object <> testMenu);              
      pm@ = pmDS.parent@;                                                
   EndDo;                                                                
   Return (pmDS.object = testMenu);                                      
  /end-free                                                              
 ppruneMnu         e                                                     

No storage is allocated for pmDS; it is used to examine the heap. ds@ contains a pointer to the current heap entry, and we are 'running' up the linked list to see if there are any transitive menu references. Clear as mud. If anybody actually reads this stuff, please send me an email - I have received absolutely *no* feedback as regards the site, yet the logs show people are visiting.



Valid HTML 3.2! Creative Commons License

BrilligWare/ chris@pando.org / revised October 2005