?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Logging: Common Processors' ??
MODULE sfm$common_processors;

{ PURPOSE:
{   This module contains common code used for both system and job routing control tables.

?? NEWTITLE := 'Global Declarations Referenced by This Module.', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$mainframe_paged_literal
*copyc ost$heap
*copyc ost$name
*copyc ost$status
*copyc sfe$audit_control_locked
*copyc sfe$routing_control_locked
*copyc sft$audit_operation_descriptor
*copyc sft$audit_selection_criteria
*copyc sft$audited_operation_set
*copyc sft$audited_operation
*copyc sft$binary_logset
*copyc sft$routing_control_table
*copyc sft$statistic_code
?? POP ??
*copyc osp$set_status_condition
*copyc sfp$routing_control
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module.', EJECT ??
?? FMT (FORMAT := OFF) ??
  VAR
    sfv$audit_operation_descriptors: [XDCL, READ, #GATE, oss$mainframe_paged_literal]
          array [sft$audited_operation] of sft$audit_operation_descriptor := [
          [sfc$asc_fs_attach_file         , 'ATTF  '],
          [sfc$asc_fs_change_attribute    , 'CHAFA '],
          [sfc$asc_fs_change_name         , 'CHAON '],
          [sfc$asc_fs_create_object       , 'CREO  '],
          [sfc$asc_fs_create_permit       , 'CREP  '],
          [sfc$asc_fs_delete_object       , 'DELO  '],
          [sfc$asc_fs_delete_permit       , 'DELP  '],
          [sfc$asc_fs_load_fap            , 'LOAFAP'],
          [sfc$asc_fs_mount_magnetic_tape , 'MOUMT '],
          [sfc$asc_job_end                , '      '],
          [sfc$asc_job_execute_program    , 'EXEP  '],
          [sfc$asc_job_process_command    , 'PROC  '],
          [sfc$asc_job_user_identification, 'USERID'],
          [sfc$asc_val_activate_capability, 'ACTC  '],
          [sfc$asc_val_change_field       , 'CHAVF '],
          [sfc$asc_val_change_field_name  , 'CHAVFN'],
          [sfc$asc_val_change_record      , 'CHAVR '],
          [sfc$asc_val_change_security_pw , 'CHASPW'],
          [sfc$asc_val_create_field       , 'CREVF '],
          [sfc$asc_val_create_record      , 'CREVR '],
          [sfc$asc_val_deact_capability   , 'DEAC  '],
          [sfc$asc_val_delete_field       , 'DELVF '],
          [sfc$asc_val_delete_record      , 'DELVR '],
          [sfc$asc_val_force_security_pw  , 'FORSPW'],
          [sfc$asc_val_force_user_password, 'FORUPW'],
          [sfc$asc_val_prevalidate_user   , 'VALU  ']];
?? FMT (FORMAT := ON) ??
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$add_audit_control', EJECT ??

{ PURPOSE:
{   Adds audit control information to a routing control table.

  PROCEDURE [XDCL, #GATE] sfp$add_audit_control
    (    routing_control_table_p: sft$routing_control_table;
         operation_set: sft$audited_operation_set;
         selection_criteria: sft$audit_selection_criteria;
         lock: boolean;
         os_heap: ^ost$heap);

    VAR
      audit_control_p: ^sft$audit_control,
      operation: sft$audited_operation,
      routing_control_p: ^sft$routing_control;

    FOR operation := LOWERVALUE (operation) TO UPPERVALUE (operation) DO
      IF operation IN operation_set THEN

{ Get a pointer to the routing control entry for the statistic code associated with the audited operation.  If
{ necessary, the routing control table entry will be created.

        routing_control_p := sfp$routing_control (sfv$audit_operation_descriptors [operation].statistic_code,
              routing_control_table_p);
        IF routing_control_p = NIL THEN
          sfp$create_routing_control (routing_control_table_p,
                sfv$audit_operation_descriptors [operation].statistic_code, os_heap, routing_control_p);
        IFEND;

{ Allocate a new audit control entry.

        ALLOCATE audit_control_p: [1 .. UPPERBOUND (selection_criteria)] IN os_heap^;

{ Initialize the audit control entry.

        audit_control_p^.locked := lock;
        audit_control_p^.operation := operation;
        audit_control_p^.selection_criteria := selection_criteria;

{ Link the audit control entry into the list of audit control entries associated with this statistic code.

        audit_control_p^.forward := routing_control_p^.audit_control_p;
        routing_control_p^.audit_control_p := audit_control_p;
      IFEND;
    FOREND;

  PROCEND sfp$add_audit_control;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$add_routing_control', EJECT ??

{ PURPOSE:
{   Adds routing control information to a routing control table.

  PROCEDURE [XDCL, #GATE] sfp$add_routing_control
    (    routing_control_table_p: sft$routing_control_table;
         statistic_code: sft$statistic_code;
         logs: sft$binary_logset;
         os_heap: ^ost$heap;
     VAR routing_control_p: ^sft$routing_control);

{ Find the entry in the routing control table for the specified statistic code.

    routing_control_p := sfp$routing_control (statistic_code, routing_control_table_p);
    IF routing_control_p = NIL THEN

{ The statistic code is not in the routing control table so add a new entry for it.

      sfp$create_routing_control (routing_control_table_p, statistic_code, os_heap, routing_control_p);
      routing_control_p^.activated_logs := logs;
    ELSE

{ The statistic code is already in the routing control table so add the specified logs
{ to the set of logs for this statistic (ignoring locked logs).

      routing_control_p^.activated_logs := routing_control_p^.activated_logs +
            (logs - routing_control_p^.locked_logs);
    IFEND;

  PROCEND sfp$add_routing_control;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$create_routing_control', EJECT ??

{ PURPOSE:
{   Allocates and initializes a new routing control table entry for the specified statistic code.

  PROCEDURE [XDCL, #GATE] sfp$create_routing_control
    (    routing_control_table_p: sft$routing_control_table;
         statistic_code: sft$statistic_code;
         os_heap: ^ost$heap;
     VAR routing_control_p: ^sft$routing_control);

    VAR
      index: 0 .. sfc$routing_control_table_size;

{ Allocate space for the routing control table entry.

    ALLOCATE routing_control_p IN os_heap^;
    routing_control_p^.statistic_code := statistic_code;
    routing_control_p^.activated_logs := $sft$binary_logset [];
    routing_control_p^.locked_logs := $sft$binary_logset [];
    routing_control_p^.limit_name := osc$null_name;
    routing_control_p^.audit_control_p := NIL;

{ Insert it as the first entry for this particular hash into the routing control table.

    index := statistic_code MOD sfc$routing_control_table_size;
    routing_control_p^.forward := routing_control_table_p^ [index];
    routing_control_table_p^ [index] := routing_control_p;

  PROCEND sfp$create_routing_control;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$delete_audit_control', EJECT ??

{ PURPOSE:
{   Deletes all unlocked audit controls for the specified operations from a routing control table.

  PROCEDURE [XDCL, #GATE] sfp$delete_audit_control
    (    routing_control_table_p: sft$routing_control_table;
         operation_set: sft$audited_operation_set;
         os_heap: ^ost$heap;
     VAR status: ost$status);

    VAR
      audit_control_p: ^sft$audit_control,
      operation: sft$audited_operation,
      routing_control_p: ^sft$routing_control,
      temp_audit_control_p: ^sft$audit_control;

    status.normal := TRUE;

  /process_operations/
    FOR operation := LOWERVALUE (operation) TO UPPERVALUE (operation) DO
      IF operation IN operation_set THEN

{ Get a pointer to the routing control entry for the statistic code associated with the audited operation.  If
{ no routing control entry exists or the audit control pointer is nil, there are no audit controls for the
{ operation.

        routing_control_p := sfp$routing_control (sfv$audit_operation_descriptors [operation].statistic_code,
              routing_control_table_p);
        IF (routing_control_p <> NIL) AND (routing_control_p^.audit_control_p <> NIL) THEN

{ Starting with the second audit control, delete any that are not locked.

          audit_control_p := routing_control_p^.audit_control_p;
          WHILE audit_control_p^.forward <> NIL DO
            IF NOT audit_control_p^.forward^.locked THEN
              temp_audit_control_p := audit_control_p^.forward;
              audit_control_p^.forward := audit_control_p^.forward^.forward;
              FREE temp_audit_control_p IN os_heap^;
            ELSE
              osp$set_status_condition (sfe$audit_control_locked, status);
              audit_control_p := audit_control_p^.forward;
            IFEND;
          WHILEND;

{ Remove the first audit control if it is not locked.

          IF NOT routing_control_p^.audit_control_p^.locked THEN
            temp_audit_control_p := routing_control_p^.audit_control_p;
            routing_control_p^.audit_control_p := routing_control_p^.audit_control_p^.forward;
            FREE temp_audit_control_p IN os_heap^;
          ELSE
            osp$set_status_condition (sfe$audit_control_locked, status);
          IFEND;
        IFEND;
      IFEND;
    FOREND;

  PROCEND sfp$delete_audit_control;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$delete_routing_control', EJECT ??

{ PURPOSE:
{   Deletes unlocked routing control information for the specified statistic and logs.

  PROCEDURE [XDCL, #GATE] sfp$delete_routing_control
    (    routing_control_table_p: sft$routing_control_table;
         statistic_code: sft$statistic_code;
         logs: sft$binary_logset;
     VAR status: ost$status);

    VAR
      routing_control_p: ^sft$routing_control;

    status.normal := TRUE;

{ Find the entry in the routing control table for the specified statistic code and remove the specified logs
{ (ignoring locked logs) from the set of activated logs.

    routing_control_p := sfp$routing_control (statistic_code, routing_control_table_p);
    IF routing_control_p <> NIL THEN
      routing_control_p^.activated_logs := routing_control_p^.activated_logs -
            (logs - routing_control_p^.locked_logs);

{ If any of the routing controls were not deleted because they were locked, return a warning error.

      IF (routing_control_p^.activated_logs * logs) <> $sft$binary_logset[] THEN
        osp$set_status_condition (sfe$routing_control_locked, status);
      IFEND;
    IFEND;

  PROCEND sfp$delete_routing_control;
?? OLDTITLE ??
?? NEWTITLE := '[XDCL, #GATE] sfp$lock_routing_control', EJECT ??

{ PURPOSE:
{   Locks the routing controls for the specified statistic and logs.

  PROCEDURE [XDCL, #GATE] sfp$lock_routing_control
    (    routing_control_table_p: sft$routing_control_table;
         statistic_code: sft$statistic_code;
         logs: sft$binary_logset;
         os_heap: ^ost$heap);

    VAR
      routing_control_p: ^sft$routing_control;

{ Find the entry in the routing control table for the specified statistic code and add the specified logs
{ to the set of locked logs.  If a routing control table entry does not exist for the statistic, one will be
{ created.

    routing_control_p := sfp$routing_control (statistic_code, routing_control_table_p);
    IF routing_control_p = NIL THEN
      sfp$create_routing_control (routing_control_table_p, statistic_code, os_heap, routing_control_p);
    IFEND;
    routing_control_p^.locked_logs := routing_control_p^.locked_logs + logs;

  PROCEND sfp$lock_routing_control;
?? OLDTITLE ??
MODEND sfm$common_processors;

