System and Subsystem classes: Difference between revisions

From m204wiki
Jump to navigation Jump to search
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."
&ldquo;system.&rdquo;
   
   
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
<pre style="xmp">
%subsys    is object subsystem
    %sys      is object system
...
    %subsys    is object subsystem
%sys:setGlobal('GOOSE', 'SAUCE')
    ...
%subsys:setGlobal('GANDER', 'SAUCE')
    %sys:setGlobal('GOOSE', 'SAUCE')
</p>
    %subsys:setGlobal('GANDER', 'SAUCE')
</pre>
   
   
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:
<pre style="xmp">
<p class="code">%(system):setString('STATUS', %status)
    %(system):setString('STATUS', %status)
print %(subsystem):string('INFO')
    print %(subsystem):string('INFO')
</p>
</pre>
 
==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 &mdash;
or it can even be a context that isn't associated with a real subsystem &mdash;
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:
<pre style="xmp">
<p class="code">%(subsystem):setString('DEBUG', 'ON')
    %(subsystem):setString('DEBUG', 'ON')
</p>
</pre>
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:
<pre style="xmp">
<p class="code">%(subsystem):context = 'DISORDER'
    %(subsystem):context = 'DISORDER'
</p>
</pre>
   
   
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===
  SIRMETH {ALLOW | DISALLOW}                  -
<p class="syntax">SIRMETH {ALLOW | DISALLOW}                  -
          {SYSTEMSET | SUBSYSTEMSET |          -
        {SYSTEMSET | SUBSYSTEMSET |          -
            SUBSYSTEMCONTEXT csubsys | ALL}    -
        SUBSYSTEMCONTEXT csubsys | ALL}    -
          [SUBSYSTEM subsys [NONPRE] ]
        [SUBSYSTEM subsys [NONPRE] ]</p>
Where:
Where:
<dl>
<table class="thJustBold">
<dt>ALLOW
<tr><th>ALLOW</th>
<dd>Indicates that requests matching the rule will be allowed to perform
<td>Indicates that requests matching the rule will be allowed to perform the indicated action.</td></tr>
the indicated action.
 
<dt>DISALLOW
<tr><th>DISALLOW</th>
<dd>Indicates that requests matching the rule will not be allowed to perform
<td>Indicates that requests matching the rule will not be allowed to perform the indicated action.</td></tr>
the indicated action.
 
<dt>SYSTEMSET
<tr><th>SYSTEMSET</th>
<dd>Indicates the ability to set system strings or globals.
<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 $setg_sys function.
<tr><th>SUBSYSTEMSET</th>
<dt>SUBSYSTEMSET
<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>
<dd>Indicates the ability to set subsytem strings or globals.
 
This applies to the SetGlobal and SetString methods in the SubSystem
<tr><th>SUBSYSTEMCONTEXT</th>
class, as well as the $setg_subsys function (when the third argument,
<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).
 
<dt>SUBSYSTEMCONTEXT
<tr><th>ALL</th>
<dd>Indicates the ability to change subsytem context to the subsystem
<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 ''csubsys''.
 
''csubsys'' can be a specific subsystem name such as SIRPRO,
<tr><th>SUBSYSTEM</th>
or it can be a wild-card such as SIR* or ???PRO.
<td>Indicates that the action is to be allowed to methods in the subsystem indicated by <var class="term">subsys</var>.
<dt>ALL
<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>.
<dd>Only allowed on a DISALLOW rule, this indicates that no extra
<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.
<dt>SUBSYSTEM
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>
<dd>Indicates that the action is to be allowed to methods in the subsystem
 
indicated by ''subsys''.
<tr><th>NONPRE</th>
''subsys'' can be a specific subsystem name such as INVENTORY, or it
<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 wild-card such as INV* or INVENTO?Y.
</table>
   
   
Note that if SUBSYSTEM is specified, the rule applies to the real subsystem
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.
being run, regardless of the current subsystem context.
For example, in the following two rules, the second <var>SIRMETH</var> rule completely encompasses the first, so the first rule is discarded:
Note also that unless followed by the keyword NONPRE, the rule only applies
<p class="code">SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOOBAR
to pre-compiled procedures in the subsystem.
SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOO*
<dt>NONPRE
</p>
<dd>Indicates that non-pre-compiled
 
procedures in the subsystem are also to be given the capabilities indicated by
A <code>SIRMETH DISALLOW ALL</code> preempts all previous rules,
the SIRMETH rule.
NONPRE must immediately follow the subsystem name.
</dl>
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:
<pre style="xmp">
    SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOOBAR
    SIRMETH ALLOW SUBSYSTEMSET SUBSYS FOO*
</pre>
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.
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:
<pre style="xmp">
    SIRMETH ALLOW SUBSYSTEMSET
    SIRMETH ALLOW SUBSYSTEMSET
    SIRMETH ALLOW SUBSYSTEMCONTEXT
</pre>
   
   
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 $setg_sys and $setg_subsys.
If so, the following rules allow everyone to do everything with system and subsystem entities:
If the third parameter of $setg_subsys (subsystem name) is specified,
<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 $setg_subsys with a subsystem
SIRMETH ALLOW SUBSYSTEMCONTEXT
name by saving the subsystem context, setting it, and then restoring it:
</p>
<pre style="xmp">
It is worth reiterating that while the <var>System</var> and <var>Subsystem</var> classes are
    %oldContext = %(subsystem):context
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>.
    %(subsystem):context = 'CUSTOMER'
If the third parameter of <var>$Setg_subsys</var> (subsystem name) is specified,
    %(subsystem):setGlobal('CUSTFILE', 'GROUP CUST2004')
no <var>SIRMETH</var> rules apply, and the user must be a system manager.
    %(subsystem):context = %oldContext
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:
</pre>
<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 $getg function or a dummy string compile-time string
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 <tt>?&</tt>) is resolved from a thread-level
global variable (that is, a variable set via <var>$Setg</var>).
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
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 $getg or a dummy string)
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 $getg or the dummy string.
   
   
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')
<pre style="xmp">
</p>
    %(subsystem):setGlobal('INVFILE', 'PERM GROUP INV2004')
</pre>
the following line
the following line
<pre style="xmp">
<p class="code">%inventoryRecords is object recordSet in ?&INVFILE
    %inventoryRecords is object recordSet in ?&INVFILE
</p>
</pre>
is resolved as
is resolved as
<pre style="xmp">
<p class="code">%inventoryRecords is object recordSet in PERM GROUP INV2004
    %inventoryRecords is object recordSet in PERM GROUP INV2004
</p>
</pre>
   
   
$SIRPARM has settings to indicate that $get or dummy string lookup
<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:
<pre style="xmp">
<p class="code">%rc = $sirparm('DUMMYSYS', 1)
    %rc = $sirparm('DUMMYSYS', 1)
</p>
</pre>
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 $getg calls:
ahead of thread-specific globals for <var>$Getg</var> calls:
<pre style="xmp">
<p class="code">%rc = $sirparm('GETGSYS', 1)
    %rc = $sirparm('GETGSYS', 1)
</p>
</pre>
   
   
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 $getg or dummy string requests,
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/Subsystem function)|String]]
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&#179;&#185;-1 bytes long.
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**31-1 bytes
long.
==System-wide objects==
==System-wide objects==
''Sirius Mods'' version 6.7 adds methods to the Janus System and Subsystem classes
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 &ldquo;system&rdquo; in system-wide
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>
<dl>
<tr class="head">
<dt>SetObject
  <th>Method</th>
<dd>Makes an object available system-wide with a
  <th>Summary</th>
specified name, as described in [[SetObject (System/Subsystem function)|SetObject]].
  <th>System</th>
<dt>GetObject
  <th>SubSystem</th>
<dd>Retrieves a copy of the specified system-wide object,
<tr>
as described in [[GetObject (System/Subsystem function)|GetObject]].
  <td><b>SetObject</b></td>
<dt>DeleteObject
  <td>Makes an object available system-wide with a specified name.</td>
<dd>Deletes the specified system-wide object,
  <td>[[SetObject (System function)|SetObject]]</td>
as described in [[DeleteObject (System/Subsystem subroutine)|DeleteObject]].
  <td>[[SetObject (Subsystem function)|SetObject]]</td>
<dt>ListOfObjects
</tr>
<dd>Returns a Stringlist containing information about system-wide objects,
<tr>
as described in [[ListOfObjects (System/Subsystem function)|ListOfObjects]].
  <td><b>GetObject</b></td>
</dl>
  <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|"List of System methods"]].
The individual <var>System</var> methods are summarized in [[List of System methods]].
<p></p>
 
The individual Subsystem methods are summarized in [[List of Subsystem methods|"List of Subsystem 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 INVENTORY, or it can be a wildcard such as INV* or INVENTO?Y.

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.