System and Subsystem classes: Difference between revisions
m (add category) |
|||
(21 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
<!-- System and Subsystem classes --> | <!-- <var>System</var> and <var>Subsystem</var> classes --> | ||
<!-- on System class page, #REDIRECT [[System and Subsystem classes]] | <!-- on System class page, #REDIRECT [[System and Subsystem classes]] | ||
on Subystem class page, #REDIRECT [[System and Subsystem classes]] --> | on Subystem class page, #REDIRECT [[System and Subsystem classes]] --> | ||
The System and Subsystem classes are collections of shared methods that | The <var>System</var> and <var>Subsystem</var> classes are collections of [[Notation conventions for methods#Shared methods|shared methods]] that | ||
operate on entities (globals, strings, objects) made | operate on entities (globals, strings, objects) made | ||
available to all users in an Online system or all users in a subsystem, | available to all users in an Online system or all users in a subsystem, | ||
or that operate on environmental entities such as the current INCLUDE | or that operate on environmental entities such as the current <var>INCLUDE</var> | ||
arguments, or the current call stack that are essentially part of the | arguments, or the current call stack that are essentially part of the "system." | ||
There are no System or Subsystem objects, per se. | There are no <var>System</var> or <var>Subsystem</var> objects, per se. | ||
That is, you cannot instantiate an instance of a System or Subsystem object, | That is, you cannot instantiate an instance of a <var>System</var> or <var>Subsystem</var> object, | ||
nor assign references from one variable to another, nor are there any | nor assign references from one variable to another, nor are there any | ||
instance-specific methods in these classes. | instance-specific methods in these classes. | ||
You can, however, declare objects of these classes. | You can, however, declare objects of these classes. | ||
The main use of such objects is to provide a short-hand way of referencing | The main use of such objects is to provide a short-hand way of referencing the classes: | ||
the classes: | <p class="code">%sys is object system | ||
< | %subsys is object subsystem | ||
... | |||
%sys:setGlobal('GOOSE', 'SAUCE') | |||
%subsys:setGlobal('GANDER', 'SAUCE') | |||
</p> | |||
</ | |||
Even though you cannot instantiate or invoke instance-specific | Even though you cannot instantiate or invoke instance-specific | ||
methods against System or Subsystem objects, you may find it | methods against <var>System</var> or <var>Subsystem</var> objects, you may find it | ||
helpful to think of there being an implicit System object | helpful to think of there being an implicit System object | ||
that contains system-wide and thread-specific context for the system, | that contains system-wide and thread-specific context for the system, | ||
and a SubSystem object for every valid subsystem context. | and a <var>SubSystem</var> object for every valid subsystem context. | ||
Still, all System and Subsystem class methods are shared methods, | Still, all <var>System</var> and <var>Subsystem</var> class methods are shared methods, | ||
so they are invokable via their class names: | so they are invokable via their class names: | ||
< | <p class="code">%(system):setString('STATUS', %status) | ||
print %(subsystem):string('INFO') | |||
</p> | |||
</ | |||
==Subsystem context== | ==Subsystem context== | ||
Subsystem class methods operate on entities associated with the current | <var>Subsystem</var> class methods operate on entities associated with the current subsystem context. | ||
subsystem context. | This context is, by default, the current subsystem in which a request is running. | ||
This context is, by default, the current subsystem in which a request | It is, possible, however, to run with a subsystem context different from the current subsystem. | ||
is running. | |||
It is, possible, however, to run with a subsystem context different from | |||
the current subsystem. | |||
This subsystem context can be a subsystem other than the one being run, | This subsystem context can be a subsystem other than the one being run, | ||
or it can even be a context that isn't associated with a real subsystem — | or it can even be a context that isn't associated with a real subsystem — | ||
the context is simply a name, and it is not required to be a started or | the context is simply a name, and it is not required to be a started or even defined subsystem. | ||
even defined subsystem. | |||
It is also possible to set a subsystem context for requests that are not even | It is also possible to set a subsystem context for requests that are not even | ||
inside a subsystem. | inside a subsystem. | ||
Line 55: | Line 48: | ||
changed inside the subsystem. | changed inside the subsystem. | ||
Once the subsystem context is set, all Subsystem class methods apply to | Once the subsystem context is set, all <var>Subsystem</var> class methods apply to | ||
that subsystem context. | that subsystem context. | ||
For example, if subsystem ORDER is entered, the following statement | For example, if subsystem ORDER is entered, the following statement | ||
sets a subsystem string for that subsystem: | sets a subsystem string for that subsystem: | ||
< | <p class="code">%(subsystem):setString('DEBUG', 'ON') | ||
</p> | |||
</ | |||
However, if the following statement is run before it, | However, if the following statement is run before it, | ||
the SetString method actually applies to the DISORDER subsystem context: | the <var>SetString</var> method actually applies to the DISORDER subsystem context: | ||
< | <p class="code">%(subsystem):context = 'DISORDER' | ||
</p> | |||
</ | |||
Since setting the subsystem context allows a request to modify entities | Since setting the subsystem context allows a request to modify entities | ||
associated with another subsystem, the ability to set subsystem context | associated with another subsystem, the ability to set subsystem context is protected. | ||
is protected. | Ordinarily, only a system manager or system administrator can set the subsystem context, though | ||
Ordinarily, only a system manager can set the subsystem context, though | the ability to set subsystem context can be controlled with <var>SIRMETH</var> rules. | ||
the ability to set subsystem context can be controlled with SIRMETH | |||
rules. | |||
==Using SIRMETH to specify security rules== | ==Using SIRMETH to specify security rules== | ||
The ability to modify system or subsystem entities gives a user the | The ability to modify system or subsystem entities gives a user the | ||
ability to cause problems in threads other than their own. | ability to cause problems in threads other than their own. | ||
As such, this capability must be protected to prevent malicious or | As such, this capability must be protected to prevent malicious or | ||
unintentional modification of system-wide or subsystem-wide | unintentional modification of system-wide or subsystem-wide entities. | ||
entities. | |||
The default protection for system-wide and subsystem-wide entities | The default protection for system-wide and subsystem-wide entities is: | ||
is: | |||
<ul> | <ul> | ||
<li>Only system managers can modify system-wide entities (system globals | <li>Only system managers can modify system-wide entities (system globals | ||
and strings, for example). | and strings, for example). | ||
<li>Only pre-compiled procedures in a subsystem can modify subsystem-wide | |||
entities. | <li>Only pre-compiled procedures in a subsystem can modify subsystem-wide entities. | ||
<li>Only system managers can set their subsystem context. | <li>Only system managers can set their subsystem context. | ||
</ul> | </ul> | ||
Line 95: | Line 84: | ||
<ul> | <ul> | ||
<li>There might be several trusted subsystems that one would want to | <li>There might be several trusted subsystems that one would want to | ||
allow to set System globals. | allow to set <var>System</var> globals. | ||
<li>One might want to set SubSystem globals in non-precompiled procedures. | |||
<li>One might want to set <var>SubSystem</var> globals in non-precompiled procedures. | |||
<li>One might want several subsystems to operate under the same subsystem | <li>One might want several subsystems to operate under the same subsystem | ||
context, that is, share subsystem entities. | context, that is, share subsystem entities. | ||
<li>For development and debugging, one might want very loose restrictions | <li>For development and debugging, one might want very loose restrictions | ||
on what programmers can and cannot do. | on what programmers can and cannot do. | ||
</ul> | </ul> | ||
While most of these problems can be worked around by giving programmers system | While most of these problems can be worked around by giving programmers system | ||
manager privileges or by having subsystems run with system manager privileges, | manager privileges or by having subsystems run with system manager privileges, | ||
this might be further than one wants to go to provide these capabilities. | this might be further than one wants to go to provide these capabilities. | ||
To ameliorate these problems, the SIRMETH command is provided. | To ameliorate these problems, the <var>SIRMETH</var> command is provided. | ||
The SIRMETH command provides a way of giving specific subsystems or all | The <var>SIRMETH</var> command provides a way of giving specific subsystems or all | ||
users access to certain System or Subsystem class capabilities. | users access to certain <var>System</var> or <var>Subsystem</var> class capabilities. | ||
Of course, the SIRMETH command itself requires system manager privileges. | Of course, the <var>SIRMETH</var> command itself requires system manager privileges. | ||
===SIRMETH command syntax=== | ===SIRMETH command syntax=== | ||
<p class="syntax">SIRMETH {ALLOW | DISALLOW} - | |||
{SYSTEMSET | SUBSYSTEMSET | - | |||
SUBSYSTEMCONTEXT csubsys | ALL} - | |||
[SUBSYSTEM subsys [NONPRE] ]</p> | |||
Where: | Where: | ||
< | <table class="thJustBold"> | ||
< | <tr><th>ALLOW</th> | ||
< | <td>Indicates that requests matching the rule will be allowed to perform the indicated action.</td></tr> | ||
the indicated action. | |||
< | <tr><th>DISALLOW</th> | ||
< | <td>Indicates that requests matching the rule will not be allowed to perform the indicated action.</td></tr> | ||
the indicated action. | |||
< | <tr><th>SYSTEMSET</th> | ||
< | <td>Indicates the ability to set system strings or globals. This applies to the <var>[[SetGlobal (System subroutine)|SetGlobal]]</var> and <var>[[SetString (System function)|SetString]]</var> methods in the <var>System</var> class, as well as the <var>[[$Setg_Sys]]</var> function.</td></tr> | ||
This applies to the SetGlobal and SetString methods in the System | |||
class, as well as the $ | <tr><th>SUBSYSTEMSET</th> | ||
< | <td>Indicates the ability to set subsytem strings or globals. This applies to the <var>[[SetGlobal (Subsystem subroutine)|SetGlobal]]</var> and <var>[[SetString (Subsystem function)|SetString]]</var> methods in the <var>SubSystem</var> class, as well as the <var>[[$Setg_Subsys]]</var> function (when the third argument, the subsystem name, is not specified).</td></tr> | ||
< | |||
This applies to the SetGlobal and SetString methods in the SubSystem | <tr><th>SUBSYSTEMCONTEXT</th> | ||
class, as well as the $ | <td>Indicates the ability to change subsytem context to the subsystem indicated by <var class="term">csubsys</var>. <var class="term">csubsys</var> can be a specific subsystem name such as <code>SIRPRO</code>, or it can be a wildcard such as <code>SIR*</code> or <code>???PRO</code>.</td></tr> | ||
the subsystem name, is not specified). | |||
< | <tr><th>ALL</th> | ||
< | <td>Only allowed on a <var>DISALLOW</var> rule, this indicates that no extra capabilities are to be provided to requests matching the rule.</td></tr> | ||
indicated by | |||
<tr><th>SUBSYSTEM</th> | |||
or it can be a | <td>Indicates that the action is to be allowed to methods in the subsystem indicated by <var class="term">subsys</var>. | ||
< | <var class="term">subsys</var> can be a specific subsystem name such as <code>INVENTORY</code>, or it can be a wildcard such as <code>INV*</code> or <code>INVENTO?Y</code>. | ||
< | <p> | ||
capabilities are to be provided to requests matching the rule. | Note that if <var>SUBSYSTEM</var> is specified, the rule applies to the real subsystem being run, regardless of the current subsystem context. | ||
< | Note also that unless followed by the keyword <var>NONPRE</var>, the rule only applies to pre-compiled procedures in the subsystem.</p></td></tr> | ||
< | |||
indicated by | <tr><th>NONPRE</th> | ||
<td>Indicates that non-pre-compiled procedures in the subsystem are also to be given the capabilities indicated by the <var>SIRMETH</var> rule. <var>NONPRE</var> must immediately follow the subsystem name.</td></tr> | |||
can be a | </table> | ||
You can specify as many <var>SIRMETH</var> rules as you want. A <var>SIRMETH</var> rule that totally encompasses a previous rule preempts that rule. | |||
For example, in the following two rules, the second <var>SIRMETH</var> rule completely encompasses the first, so the first rule is discarded: | |||
<p class="code">SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOOBAR | |||
SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOO* | |||
</p> | |||
< | |||
A <code>SIRMETH DISALLOW ALL</code> preempts all previous rules, | |||
</ | |||
A SIRMETH rule that | |||
totally encompasses a previous rule preempts that rule. | |||
For example, in the following two rules, | |||
the second SIRMETH rule completely encompasses the first, so the first | |||
rule is discarded: | |||
< | |||
</ | |||
A SIRMETH DISALLOW ALL preempts all previous rules, | |||
so it is a way of starting from a clean slate. | so it is a way of starting from a clean slate. | ||
If you place a SIRMETH DISALLOW ALL at the start of a | If you place a <code>SIRMETH DISALLOW ALL</code> at the start of a | ||
sequence of SIRMETH rules (most likely in a procedure), those rules | sequence of <var>SIRMETH</var> rules (most likely in a procedure), those rules | ||
can be run again and again, perhaps after some of the rules have been | can be run again and again, perhaps after some of the rules have been modified. | ||
modified. | Of course, in the interval between the <code>SIRMETH DISALLOW ALL</code> and the | ||
Of course, in the interval between the SIRMETH DISALLOW ALL and the | |||
subsequent rules, some ordinarily legal requests might be disallowed, | subsequent rules, some ordinarily legal requests might be disallowed, | ||
so it is probably not a good idea to reapply SIRMETH rules in | so it is probably not a good idea to reapply <var>SIRMETH</var> rules in a production region. | ||
a production region. | |||
Generally, SIRMETH rules are placed in the CCAIN stream or in | Generally, <var>SIRMETH</var> rules are placed in the CCAIN stream or in | ||
a procedure INCLUDE'd in the CCAIN stream. | a procedure <var>INCLUDE</var>'d in the CCAIN stream. | ||
The reason for the NONPRE keyword is that many debugging and development | The reason for the <var>NONPRE</var> keyword is that many debugging and development | ||
subsystems allow users (programmers, typically) to run arbitrary code | subsystems allow users (programmers, typically) to run arbitrary code from inside the subsystem. | ||
from inside the subsystem. | Typically, this arbitrary code is run from a non-pre-compiled procedure that includes the programmer's code. | ||
Typically, this arbitrary code is run from a non-pre-compiled | |||
procedure that includes the programmer's code. | |||
To prevent such code from picking up the subsystem's capabilities, | To prevent such code from picking up the subsystem's capabilities, | ||
System and Subsystem class security does not apply SIRMETH rules | System and <var>Subsystem</var> class security does not apply <var>SIRMETH</var> rules | ||
to non-pre-compiled procedures, unless the NONPRE keyword is specified | to non-pre-compiled procedures, unless the <var>NONPRE</var> keyword is specified on the rule. | ||
on the rule. | <p> | ||
Since most subsystems don't allow users to run arbitrary code inside | Since most subsystems don't allow users to run arbitrary code inside them, and since it is quite likely that you might want to set | ||
them, and since it is quite likely that you might want to set | subsystem globals or switch subsystem contexts inside a non-pre-compiled procedure, it is probably a good idea to specify <var>NONPRE</var> for those | ||
subsystem globals or switch subsystem contexts inside a non-pre-compiled | subsystems.</p> | ||
procedure, it is probably a good idea to specify NONPRE for those | |||
subsystems. | |||
</ | |||
It is worth reiterating that while the System and Subsystem classes are | In a development environment, to avoid the effort of modifying multiple individual <var>SIRMETH</var> rules, | ||
the preferred interface for setting system and subsystem globals, | you may be willing to risk letting programmers modify any system or subsystem entity. | ||
the SIRMETH rules also apply to $ | If so, the following rules allow everyone to do everything with system and subsystem entities: | ||
If the third parameter of $ | <p class="code">SIRMETH ALLOW SUBSYSTEMSET | ||
no SIRMETH rules apply, and the user must be a system manager. | SIRMETH ALLOW SUBSYSTEMSET | ||
You can get the same effect as a $ | SIRMETH ALLOW SUBSYSTEMCONTEXT | ||
name by saving the subsystem context, setting it, and then restoring it: | </p> | ||
< | It is worth reiterating that while the <var>System</var> and <var>Subsystem</var> classes are | ||
the preferred interface for setting system and subsystem globals, the <var>SIRMETH</var> rules also apply to <var>$Setg_sys</var> and <var>$Setg_subsys</var>. | |||
If the third parameter of <var>$Setg_subsys</var> (subsystem name) is specified, | |||
no <var>SIRMETH</var> rules apply, and the user must be a system manager. | |||
You can get the same effect as a <var>$Setg_subsys</var> with a subsystem name by saving the subsystem context, setting it, and then restoring it: | |||
</ | <p class="code">%oldContext = %(subsystem):context | ||
%(subsystem):context = 'CUSTOMER' | |||
%(subsystem):setGlobal('CUSTFILE', 'GROUP CUST2004') | |||
%(subsystem):context = %oldContext | |||
</p> | |||
==System and subsystem globals and strings== | ==System and subsystem globals and strings== | ||
Typically, a $ | Typically, a <var>$Getg</var> function or a dummy string compile-time string (that is, something that begins with <code>?&</code>) is resolved from a thread-level | ||
(that is, something that begins with < | global variable (that is, a variable set via <var>$Setg</var>). | ||
global variable (that is, a variable set via $ | Often, however, all requests in an Online or subsystem will use the same value for some of these globals, so it seems appealing for these | ||
Often, however, all requests in an Online or subsystem will use the | users to share a copy of those globals rather than each wasting GTBL space to hold a copy for each thread. | ||
same value for some of these globals, so it seems appealing for these | |||
users to share a copy of those globals rather than each wasting GTBL | |||
space to hold a copy for each thread. | |||
System and subsystem globals make this feasible. | System and subsystem globals make this feasible. | ||
By default, if a global reference (either a $ | By default, if a global reference (either a <var>$Getg</var> or a dummy string) | ||
cannot be resolved with thread-level globals, subsystem and then system | cannot be resolved with thread-level globals, subsystem and then system globals will be searched. | ||
globals will be searched. | If one of these matches the requested global, that global will be returned for the <var>$Getg</var> or the dummy string. | ||
If one of these matches the requested global, that global will be | |||
returned for the $ | |||
For example, if the following statement exists in a subsystem initialization | For example, if the following statement exists in a subsystem initialization procedure: | ||
procedure: | <p class="code">%(subsystem):setGlobal('INVFILE', 'PERM GROUP INV2004') | ||
< | </p> | ||
</ | |||
the following line | the following line | ||
< | <p class="code">%inventoryRecords is object recordSet in ?&INVFILE | ||
</p> | |||
</ | |||
is resolved as | is resolved as | ||
< | <p class="code">%inventoryRecords is object recordSet in PERM GROUP INV2004 | ||
</p> | |||
</ | |||
$ | <var>[[$SirParm]]</var> has settings to indicate that <var>$Get</var> or dummy string lookup | ||
should use subsystem or system globals ahead of thread-specific globals. | should use subsystem or system globals ahead of thread-specific globals. | ||
For example, the following statement | For example, the following statement indicates that subsystem or system globals are to be used ahead of thread-specific | ||
indicates that subsystem or system globals are to be used ahead of thread-specific | |||
globals for dummy strings: | globals for dummy strings: | ||
< | <p class="code">%rc = $sirparm('DUMMYSYS', 1) | ||
</p> | |||
</ | |||
And the following call indicates that subsystem or system globals are to be used | And the following call indicates that subsystem or system globals are to be used | ||
ahead of thread-specific globals for $ | ahead of thread-specific globals for <var>$Getg</var> calls: | ||
< | <p class="code">%rc = $sirparm('GETGSYS', 1) | ||
</p> | |||
</ | |||
Note that system and subsystem globals are different from system and | Note that system and subsystem globals are different from system and subsystem strings. | ||
subsystem strings. | The latter are never returned for <var>$Getg</var> or dummy string requests, | ||
The latter are never returned for $ | and they can only be retrieved via the <var>[[String (System function)|String]]</var> function. | ||
and they can only be retrieved via the [[String (System | Also, system and subsystem global values can never be longer than 255 bytes, whereas | ||
function. | system and subsystem strings are <var>Longstrings</var>, which can be up to 2³¹-1 bytes long. | ||
Also, system and subsystem global values can never be longer than 255 bytes, | |||
whereas | |||
system and subsystem strings are | |||
long. | |||
==System-wide objects== | ==System-wide objects== | ||
The <var class="product">Janus</var> <var>System</var> and <var>Subsystem</var> classes have methods | |||
that make designated objects available to all users in an Online or of a subsystem. | that make designated objects available to all users in an Online or of a subsystem. | ||
Such objects, referred to as '''system-wide''' objects, are made available | Such objects, referred to as '''system-wide''' objects, are made available via deep copy, so only | ||
via deep copy, so only | deep-copyable (see [[Copying objects]]) objects are eligible. | ||
deep copyable (see [[Copying objects]]) objects are eligible. | |||
An object becomes system-wide if and only if it is saved by the System class | An object becomes system-wide if and only if it is saved by the <var>System</var> class | ||
SetObject method or by the Subsystem class SetObject method. | <var>[[SetObject (System function)|SetObject]]</var> method or by the <var>Subsystem</var> class <var>[[SetObject (Subsystem function)|SetObject]]</var> method. | ||
If by the System class SetObject method, the | If by the <var>System</var> class <var>SetObject</var> method, the "system" in system-wide | ||
refers to all users in the Online; if by the Subsystem SetObject method, all | refers to all users in the Online; if by the <var>Subsystem</var> <var>SetObject</var> method, all | ||
users in the current or a specified subsystem. | users in the current or a specified subsystem. | ||
System-wide objects belong to a namespace that is not the same as | System-wide objects belong to a namespace that is not the same as that for <var>System</var> and <var>Subsystem</var> longstrings. | ||
that for System and Subsystem longstrings. | That is, both a <var>System</var> longstring and a system-wide object may be called by the same name at the same time. | ||
That is, both a System longstring and a system-wide object may be called by the | |||
same name at the same time. | |||
The methods that work with system-wide objects are one System and one Subsystem | The methods that work with system-wide objects are one <var>System</var> and one <var>Subsystem</var> class version of each of the following: | ||
class version of each of the following: | <table> | ||
< | <tr class="head"> | ||
< | <th>Method</th> | ||
< | <th>Summary</th> | ||
specified name | <th>System</th> | ||
< | <th>SubSystem</th> | ||
< | <tr> | ||
<td><b>SetObject</b></td> | |||
< | <td>Makes an object available system-wide with a specified name.</td> | ||
< | <td>[[SetObject (System function)|SetObject]]</td> | ||
<td>[[SetObject (Subsystem function)|SetObject]]</td> | |||
< | </tr> | ||
< | <tr> | ||
<td><b>GetObject</b></td> | |||
</ | <td>Retrieves a copy of the specified system-wide object.</td> | ||
<td>[[GetObject (System function)|GetObject]]</td> | |||
<td>[[GetObject (Subsystem function)|GetObject]]</td> | |||
</tr> | |||
<tr> | |||
<td><b>DeleteObject</b></td> | |||
<td>Deletes the specified system-wide object.</td> | |||
<td>[[DeleteObject (System subroutine)|DeleteObject]]</td> | |||
<td>[[DeleteObject (Subsystem subroutine)|DeleteObject]]</td> | |||
</tr> | |||
<tr> | |||
<td><b>ListOfObjects</b></td> | |||
<td>Returns a <var>Stringlist</var> containing information about system-wide objects</td> | |||
<td>[[ListOfObjects (System function)|ListOfObjects]]</td> | |||
<td>[[ListOfObjects (Subsystem function)|ListOfObjects]]</td> | |||
</tr> | |||
</table> | |||
==Lists of System and Subsystem methods== | ==Lists of System and Subsystem methods== | ||
The individual System methods are summarized in [[List of System methods | The individual <var>System</var> methods are summarized in [[List of System methods]]. | ||
< | |||
The individual <var>Subsystem</var> methods are summarized in [[List of Subsystem methods]]. | |||
[[Category:System classes]] |
Latest revision as of 19:13, 20 April 2018
The System and Subsystem classes are collections of shared methods that operate on entities (globals, strings, objects) made available to all users in an Online system or all users in a subsystem, or that operate on environmental entities such as the current INCLUDE arguments, or the current call stack that are essentially part of the "system."
There are no System or Subsystem objects, per se. That is, you cannot instantiate an instance of a System or Subsystem object, nor assign references from one variable to another, nor are there any instance-specific methods in these classes. You can, however, declare objects of these classes. The main use of such objects is to provide a short-hand way of referencing the classes:
%sys is object system %subsys is object subsystem ... %sys:setGlobal('GOOSE', 'SAUCE') %subsys:setGlobal('GANDER', 'SAUCE')
Even though you cannot instantiate or invoke instance-specific methods against System or Subsystem objects, you may find it helpful to think of there being an implicit System object that contains system-wide and thread-specific context for the system, and a SubSystem object for every valid subsystem context. Still, all System and Subsystem class methods are shared methods, so they are invokable via their class names:
%(system):setString('STATUS', %status) print %(subsystem):string('INFO')
Subsystem context
Subsystem class methods operate on entities associated with the current subsystem context. This context is, by default, the current subsystem in which a request is running. It is, possible, however, to run with a subsystem context different from the current subsystem. This subsystem context can be a subsystem other than the one being run, or it can even be a context that isn't associated with a real subsystem — the context is simply a name, and it is not required to be a started or even defined subsystem. It is also possible to set a subsystem context for requests that are not even inside a subsystem.
When a subsystem is entered, the subsystem context is automatically set to the name of the one being entered. When the subsystem is exited, the context is set back to the subsystem context in effect at entry to the subsystem, whether or not the subsystem was changed inside the subsystem.
Once the subsystem context is set, all Subsystem class methods apply to that subsystem context. For example, if subsystem ORDER is entered, the following statement sets a subsystem string for that subsystem:
%(subsystem):setString('DEBUG', 'ON')
However, if the following statement is run before it, the SetString method actually applies to the DISORDER subsystem context:
%(subsystem):context = 'DISORDER'
Since setting the subsystem context allows a request to modify entities associated with another subsystem, the ability to set subsystem context is protected. Ordinarily, only a system manager or system administrator can set the subsystem context, though the ability to set subsystem context can be controlled with SIRMETH rules.
Using SIRMETH to specify security rules
The ability to modify system or subsystem entities gives a user the ability to cause problems in threads other than their own. As such, this capability must be protected to prevent malicious or unintentional modification of system-wide or subsystem-wide entities.
The default protection for system-wide and subsystem-wide entities is:
- Only system managers can modify system-wide entities (system globals and strings, for example).
- Only pre-compiled procedures in a subsystem can modify subsystem-wide entities.
- Only system managers can set their subsystem context.
While these rules prevent intentional or unintentional tampering with system or subsystem entities, they can also be onerous:
- There might be several trusted subsystems that one would want to allow to set System globals.
- One might want to set SubSystem globals in non-precompiled procedures.
- One might want several subsystems to operate under the same subsystem context, that is, share subsystem entities.
- For development and debugging, one might want very loose restrictions on what programmers can and cannot do.
While most of these problems can be worked around by giving programmers system manager privileges or by having subsystems run with system manager privileges, this might be further than one wants to go to provide these capabilities.
To ameliorate these problems, the SIRMETH command is provided. The SIRMETH command provides a way of giving specific subsystems or all users access to certain System or Subsystem class capabilities. Of course, the SIRMETH command itself requires system manager privileges.
SIRMETH command syntax
SIRMETH {ALLOW | DISALLOW} - {SYSTEMSET | SUBSYSTEMSET | - SUBSYSTEMCONTEXT csubsys | ALL} - [SUBSYSTEM subsys [NONPRE] ]
Where:
ALLOW | Indicates that requests matching the rule will be allowed to perform the indicated action. |
---|---|
DISALLOW | Indicates that requests matching the rule will not be allowed to perform the indicated action. |
SYSTEMSET | Indicates the ability to set system strings or globals. This applies to the SetGlobal and SetString methods in the System class, as well as the $Setg_Sys function. |
SUBSYSTEMSET | Indicates the ability to set subsytem strings or globals. This applies to the SetGlobal and SetString methods in the SubSystem class, as well as the $Setg_Subsys function (when the third argument, the subsystem name, is not specified). |
SUBSYSTEMCONTEXT | Indicates the ability to change subsytem context to the subsystem indicated by csubsys. csubsys can be a specific subsystem name such as SIRPRO , or it can be a wildcard such as SIR* or ???PRO . |
ALL | Only allowed on a DISALLOW rule, this indicates that no extra capabilities are to be provided to requests matching the rule. |
SUBSYSTEM | Indicates that the action is to be allowed to methods in the subsystem indicated by subsys.
subsys can be a specific subsystem name such as Note that if SUBSYSTEM is specified, the rule applies to the real subsystem being run, regardless of the current subsystem context. Note also that unless followed by the keyword NONPRE, the rule only applies to pre-compiled procedures in the subsystem. |
NONPRE | Indicates that non-pre-compiled procedures in the subsystem are also to be given the capabilities indicated by the SIRMETH rule. NONPRE must immediately follow the subsystem name. |
You can specify as many SIRMETH rules as you want. A SIRMETH rule that totally encompasses a previous rule preempts that rule. For example, in the following two rules, the second SIRMETH rule completely encompasses the first, so the first rule is discarded:
SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOOBAR SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOO*
A SIRMETH DISALLOW ALL
preempts all previous rules,
so it is a way of starting from a clean slate.
If you place a SIRMETH DISALLOW ALL
at the start of a
sequence of SIRMETH rules (most likely in a procedure), those rules
can be run again and again, perhaps after some of the rules have been modified.
Of course, in the interval between the SIRMETH DISALLOW ALL
and the
subsequent rules, some ordinarily legal requests might be disallowed,
so it is probably not a good idea to reapply SIRMETH rules in a production region.
Generally, SIRMETH rules are placed in the CCAIN stream or in a procedure INCLUDE'd in the CCAIN stream.
The reason for the NONPRE keyword is that many debugging and development subsystems allow users (programmers, typically) to run arbitrary code from inside the subsystem. Typically, this arbitrary code is run from a non-pre-compiled procedure that includes the programmer's code. To prevent such code from picking up the subsystem's capabilities, System and Subsystem class security does not apply SIRMETH rules to non-pre-compiled procedures, unless the NONPRE keyword is specified on the rule.
Since most subsystems don't allow users to run arbitrary code inside them, and since it is quite likely that you might want to set subsystem globals or switch subsystem contexts inside a non-pre-compiled procedure, it is probably a good idea to specify NONPRE for those subsystems.
In a development environment, to avoid the effort of modifying multiple individual SIRMETH rules, you may be willing to risk letting programmers modify any system or subsystem entity. If so, the following rules allow everyone to do everything with system and subsystem entities:
SIRMETH ALLOW SUBSYSTEMSET SIRMETH ALLOW SUBSYSTEMSET SIRMETH ALLOW SUBSYSTEMCONTEXT
It is worth reiterating that while the System and Subsystem classes are the preferred interface for setting system and subsystem globals, the SIRMETH rules also apply to $Setg_sys and $Setg_subsys. If the third parameter of $Setg_subsys (subsystem name) is specified, no SIRMETH rules apply, and the user must be a system manager. You can get the same effect as a $Setg_subsys with a subsystem name by saving the subsystem context, setting it, and then restoring it:
%oldContext = %(subsystem):context %(subsystem):context = 'CUSTOMER' %(subsystem):setGlobal('CUSTFILE', 'GROUP CUST2004') %(subsystem):context = %oldContext
System and subsystem globals and strings
Typically, a $Getg function or a dummy string compile-time string (that is, something that begins with ?&
) is resolved from a thread-level
global variable (that is, a variable set via $Setg).
Often, however, all requests in an Online or subsystem will use the same value for some of these globals, so it seems appealing for these
users to share a copy of those globals rather than each wasting GTBL space to hold a copy for each thread.
System and subsystem globals make this feasible.
By default, if a global reference (either a $Getg or a dummy string) cannot be resolved with thread-level globals, subsystem and then system globals will be searched. If one of these matches the requested global, that global will be returned for the $Getg or the dummy string.
For example, if the following statement exists in a subsystem initialization procedure:
%(subsystem):setGlobal('INVFILE', 'PERM GROUP INV2004')
the following line
%inventoryRecords is object recordSet in ?&INVFILE
is resolved as
%inventoryRecords is object recordSet in PERM GROUP INV2004
$SirParm has settings to indicate that $Get or dummy string lookup should use subsystem or system globals ahead of thread-specific globals. For example, the following statement indicates that subsystem or system globals are to be used ahead of thread-specific globals for dummy strings:
%rc = $sirparm('DUMMYSYS', 1)
And the following call indicates that subsystem or system globals are to be used ahead of thread-specific globals for $Getg calls:
%rc = $sirparm('GETGSYS', 1)
Note that system and subsystem globals are different from system and subsystem strings. The latter are never returned for $Getg or dummy string requests, and they can only be retrieved via the String function. Also, system and subsystem global values can never be longer than 255 bytes, whereas system and subsystem strings are Longstrings, which can be up to 2³¹-1 bytes long.
System-wide objects
The Janus System and Subsystem classes have methods that make designated objects available to all users in an Online or of a subsystem. Such objects, referred to as system-wide objects, are made available via deep copy, so only deep-copyable (see Copying objects) objects are eligible.
An object becomes system-wide if and only if it is saved by the System class SetObject method or by the Subsystem class SetObject method. If by the System class SetObject method, the "system" in system-wide refers to all users in the Online; if by the Subsystem SetObject method, all users in the current or a specified subsystem.
System-wide objects belong to a namespace that is not the same as that for System and Subsystem longstrings. That is, both a System longstring and a system-wide object may be called by the same name at the same time.
The methods that work with system-wide objects are one System and one Subsystem class version of each of the following:
Method | Summary | System | SubSystem |
---|---|---|---|
SetObject | Makes an object available system-wide with a specified name. | SetObject | SetObject |
GetObject | Retrieves a copy of the specified system-wide object. | GetObject | GetObject |
DeleteObject | Deletes the specified system-wide object. | DeleteObject | DeleteObject |
ListOfObjects | Returns a Stringlist containing information about system-wide objects | ListOfObjects | ListOfObjects |
Lists of System and Subsystem methods
The individual System methods are summarized in List of System methods.
The individual Subsystem methods are summarized in List of Subsystem methods.