?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Deadstart : Manage Interval Password' ??
MODULE dsm$manage_interval_password;

{ PURPOSE:
{   This module contains the procedures that manage the Operation Password data, Operation Interval data
{   and the Main Window Lock data that is saved in VCU.  This code is not allowed to be used on a 93X
{   mainframe because of the inability to access VCU after DFT relocates.

?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc dse$interval_password_errors
*copyc dst$signal_contents
?? POP ??
*copyc clp$convert_integer_to_string
*copyc dpp$get_next_line
*copyc dpp$put_critical_message
*copyc dpp$put_next_line
*copyc dsp$access_vcu_cda_data
*copyc dsp$get_data_from_rdf
*copyc dsp$store_data_in_rdf
*copyc jmp$convert_date_time_dif_to_us
*copyc osp$fatal_system_error
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc osp$unpack_status_condition
*copyc pmp$get_compact_date_time
*copyc pmp$get_microsecond_clock
*copyc pmp$verify_compact_date
*copyc syp$ascii_to_binary
*copyc syp$crack_command
*copyc syp$get_token
*copyc syp$process_deadstart_status
?? EJECT ??
*copyc dpv$lock_main_window
*copyc dpv$secure_input_line
*copyc dpv$system_core_display
*copyc dsv$mainframe_type
*copyc dsv$sub_mainframe_type
*copyc syv$reading_dcfile
?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  TYPE
    t$password = RECORD
      CASE boolean OF
      = TRUE =
        password: string (7),
      = FALSE =
        encrypted_password: dst$vcu_encrypted_password,
      CASEND,
    RECEND,

    t$rdf_password_data = RECORD
      password_initialized: boolean,
      encrypted_password: dst$vcu_encrypted_password,
    RECEND,

    t$token = RECORD
      retrieved: boolean,
      data: ost$string,
      kind: t$token_kind,
      number: t$token_integer,
    RECEND,

    t$token_integer = RECORD
      value: integer,
      minimum: 0 .. 0ffff(16),
      maximum: 0 .. 0ffff(16),
    RECEND,

    t$token_kind = (c$tk_password_value, c$tk_yes_no_value, c$tk_integer_value);

?? OLDTITLE ??
?? NEWTITLE := 'change_password', EJECT ??

{ PURPOSE:
{   This procedure changes the password from its encrypted format back to its readable format or
{   it changes the password from its readable format into its encrypted format.

  PROCEDURE change_password
    (    encrypt_password: boolean;
     VAR password: t$password);

    VAR
      index: 0 .. 0ff(16),
      temp_password: t$password;

    temp_password := password;
    FOR index := LOWERBOUND (dst$vcu_encrypted_password) TO UPPERBOUND (dst$vcu_encrypted_password) DO
      IF encrypt_password THEN
        temp_password.encrypted_password [index] :=
              temp_password.encrypted_password [index] - dsc$vcu_password_mask;
      ELSE
        temp_password.encrypted_password [index] :=
              temp_password.encrypted_password [index] + dsc$vcu_password_mask;
      IFEND;
    FOREND;
    password.encrypted_password [1] := temp_password.encrypted_password [4];
    password.encrypted_password [2] := temp_password.encrypted_password [7];
    password.encrypted_password [3] := temp_password.encrypted_password [5];
    password.encrypted_password [4] := temp_password.encrypted_password [1];
    password.encrypted_password [5] := temp_password.encrypted_password [3];
    password.encrypted_password [6] := temp_password.encrypted_password [6];
    password.encrypted_password [7] := temp_password.encrypted_password [2];

  PROCEND change_password;
?? OLDTITLE ??
?? NEWTITLE := 'get_data', EJECT ??

{ PURPOSE:
{   This procedure retrieves the individual data for the SETOP and SETOI System Core Commands.

  PROCEDURE get_data
    (    id: dpt$window_id;
         question_text_1: string ( * );
         question_text_2: string ( * );
     VAR token: t$token);

    VAR
      display_string: string (osc$max_string_size),
      index: 0 .. 0ff(16),
      line_received: boolean,
      local_status: ost$status,
      loop_count: 0 .. 0ff(16),
      string_length: integer,
      text: string (70),
      token_index: 0 .. 255;

    token.retrieved := FALSE;
    loop_count := 3;

   /retrieve_answer/
    WHILE TRUE DO
      IF loop_count <= 0 THEN
        dpp$put_next_line (id, '         Allowable retries for the command exceeded, command aborted.',
              local_status);
        dpp$put_next_line (id, ' ', local_status);
        RETURN;
      ELSE
        dpp$put_next_line (id, ' ', local_status);
        loop_count := loop_count - 1;
      IFEND;

      dpp$put_next_line (id, question_text_1, local_status);
      IF question_text_2 <> ' ' THEN
        dpp$put_next_line (id, question_text_2, local_status);
      IFEND;

      text := ' ';
      IF token.kind = c$tk_password_value THEN
        dpv$secure_input_line.window_id := id;
        dpv$secure_input_line.secure := TRUE;
      IFEND;
      dpp$get_next_line (id, osc$wait, text, line_received);
      IF token.kind = c$tk_password_value THEN
        dpv$secure_input_line.secure := FALSE;
      IFEND;
      IF (text = ' ') OR NOT line_received THEN
        CYCLE /retrieve_answer/;
      IFEND;

      display_string := ' ';
      IF token.kind <> c$tk_password_value THEN
        display_string (3, *) := text;
      IFEND;
      dpp$put_next_line (id, display_string (1, 72), local_status);

      token_index := 1;
      syp$get_token (text, TRUE {upper_case}, token_index, token.data, local_status);
      IF NOT local_status.normal THEN
        dpp$put_next_line (id, 'ERROR -- Invalid value, enter valid value.', local_status);
        CYCLE /retrieve_answer/;
      IFEND;

      CASE token.kind OF
      = c$tk_password_value =
        IF token.data.size <> 7 THEN
          dpp$put_next_line (id, 'ERROR -- The PASSWORD entered is invalid.', local_status);
          CYCLE /retrieve_answer/;
        IFEND;
        FOR index := 1 TO token.data.size DO
          IF NOT ((token.data.value (index) >= 'A') AND (token.data.value (index) <= 'Z')) AND
                NOT ((token.data.value (index) >= '0') AND (token.data.value (index) <= '9')) THEN
            dpp$put_next_line (id, 'ERROR -- The PASSWORD entered is invalid.',
                  local_status);
            CYCLE /retrieve_answer/;
          IFEND;
        FOREND;

      = c$tk_yes_no_value =
        IF (token.data.value (1, token.data.size) <> 'YES') AND
              (token.data.value (1, token.data.size) <> 'NO') THEN
          dpp$put_next_line (id, 'ERROR -- Enter YES or NO.', local_status);
          CYCLE /retrieve_answer/;
        IFEND;

      = c$tk_integer_value =
        syp$ascii_to_binary (token.data.value (1, token.data.size), 10, token.number.value, local_status);
        IF NOT local_status.normal THEN
          dpp$put_next_line (id, 'ERROR -- Invalid value, enter valid value.', local_status);
          CYCLE /retrieve_answer/;
        IFEND;
        IF (token.number.value < token.number.minimum) OR (token.number.value > token.number.maximum) THEN
          STRINGREP (display_string, string_length, 'ERROR -- The value must be between ',
                token.number.minimum, ' and ', token.number.maximum, '.');
          dpp$put_next_line (id, display_string (1, string_length), local_status);
          CYCLE /retrieve_answer/;
        IFEND;
      ELSE
      CASEND;

      token.retrieved := TRUE;
      EXIT /retrieve_answer/;
    WHILEND /retrieve_answer/;

  PROCEND get_data;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$change_operation_password', EJECT ??

{ PURPOSE:
{   This procedure changes the current operation password that is stored in VCU.  It first checks that the
{   password parameter matches the password saved in VCU.  It also validates the new password before saving
{   it in VCU.

  PROCEDURE [XDCL, #GATE] dsp$change_operation_password
    (    old_password: ost$name;
         new_password: ost$name;
     VAR status: ost$status);

    VAR
      index: 0 .. 0ff(16),
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      rdf_password_data: t$rdf_password_data,
      vcu_password: t$password;

    status.normal := TRUE;
    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      osp$set_status_condition (dse$command_not_allowed, status);
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. possible disk error.', ^status);
    IFEND;

    IF NOT password_data.password_initialized THEN
      osp$set_status_condition (dse$no_password_exists, status);
      RETURN;
    IFEND;

    vcu_password.encrypted_password := password_data.encrypted_password;
    change_password (FALSE, vcu_password);
    IF vcu_password.password <> old_password (1, 7) THEN
      osp$set_status_condition (dse$invalid_password, status);
      RETURN;
    IFEND;

    IF new_password (7) = ' ' THEN
      osp$set_status_condition (dse$seven_character_password, status);
      RETURN;
    IFEND;

    FOR index := 1 TO 7 DO
      IF NOT ((new_password (index) >= 'A') AND (new_password (index) <= 'Z')) AND
            NOT ((new_password (index) >= '0') AND (new_password (index) <= '9')) THEN
        osp$set_status_condition (dse$alphanumeric_password, status);
        RETURN;
      IFEND;
    FOREND;

    vcu_password.password := new_password (1, 7);
    change_password (TRUE, vcu_password);

    password_data.password_initialized := TRUE;
    password_data.encrypted_password := vcu_password.encrypted_password;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. possible disk error', ^status);
    IFEND;

    rdf_password_data.password_initialized := TRUE;
    rdf_password_data.encrypted_password := password_data.encrypted_password;
    dsp$store_data_in_rdf (dsc$rdf_password_interval_data, dsc$rdf_production, #SEQ (rdf_password_data));

  PROCEND dsp$change_operation_password;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$check_interval', EJECT ??

{ PURPOSE:
{   This procedure is called once per deadstart and at the top of each hour to check that the Operation
{   Interval has not expired.  If the time has expired then the system is stepped.  This code is only
{   valid if an interval has been initialized.

  PROCEDURE [XDCL, #GATE] dsp$check_interval;

    VAR
      current_frc: jmt$clock_time,
      error_string: string (72),
      local_status: ost$status,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * );

    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
       RETURN;
    IFEND;

    IF dsv$sub_mainframe_type <> dsc$smt_china_mainframe THEN

{ Temporary test and exit to compensate for service processor problem.

      IF dsv$mainframe_type = dsc$mt_2000_mainframe THEN
        RETURN;
      IFEND;

{ Temporary test and exit to compensate for dedicated load device problem, 962.

      IF dsv$mainframe_type = dsc$mt_962_972_mainframe THEN
        RETURN;
      IFEND;

{ Temporary test and exit to compensate for dedicated load device problem, 992.

      IF (dsv$mainframe_type = dsc$mt_992_mainframe) THEN
        RETURN;
      IFEND;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. .', ^local_status);
    IFEND;

    IF NOT password_data.interval_initialized THEN
      RETURN;
    IFEND;

    error_string := ' ';
    pmp$get_microsecond_clock (current_frc, local_status);
    IF password_data.interval_expired OR (current_frc > password_data.expiration_frc) THEN
      error_string := 'The System Operation Interval has expired.';
      password_data.interval_expired := TRUE;
    ELSEIF current_frc < password_data.saved_current_frc THEN
      error_string := 'The current FRC appears damaged, expiration interval unknown.';
      password_data.interval_expired := TRUE;
    IFEND;

    password_data.saved_current_frc := current_frc;
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device - ', ^local_status);
    IFEND;

    IF error_string <> ' ' THEN
      osp$fatal_system_error (error_string, NIL);
    IFEND;

  PROCEND dsp$check_interval;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$check_password_for_inisd', EJECT ??

{ PURPOSE:
{   This procedure checks the password for The INISD System Core Command on China mainframes.

  PROCEDURE [XDCL] dsp$check_password_for_inisd
    (    id: dpt$window_id;
     VAR password_valid: boolean);

    VAR
      local_status: ost$status,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      token: t$token,
      vcu_password: t$password;

    password_valid := TRUE;
    IF dsv$sub_mainframe_type <> dsc$smt_china_mainframe THEN
      RETURN;
    IFEND;

    password_valid := FALSE;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device.', ^local_status);
    IFEND;

    IF NOT password_data.password_initialized THEN
      dpp$put_next_line (id, 'ERROR -- A SETOP command has NOT yet been entered, it must be', local_status);
      dpp$put_next_line (id, '         used before the INISD command.', local_status);
      RETURN;
    IFEND;

    { Check that the user of the command has the authorization to use this command.

    vcu_password.encrypted_password := password_data.encrypted_password;
    change_password (FALSE, vcu_password);
    token.kind := c$tk_password_value;
    get_data (id, 'Enter the Operation Password:', '(it will not be displayed on the screen)', token);
    IF NOT token.retrieved THEN
      RETURN;
    IFEND;
    IF token.data.value (1, token.data.size) <> vcu_password.password THEN
      dpp$put_next_line (id, 'ERROR -- Invalid PASSWORD entered, it does not match the old PASSWORD saved.',
            local_status);
      dpp$put_next_line (id, '         The command has aborted. ', local_status);
      dpp$put_next_line (id, ' ', local_status);
      RETURN;
    IFEND;

    dpp$put_next_line (id, 'Parameter entry for the INISD command has been completed.', local_status);
    dpp$put_next_line (id, ' ', local_status);
    password_valid := TRUE;

  PROCEND dsp$check_password_for_inisd;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$check_saved_passwords', EJECT ??

{ PURPOSE:
{   This procedure checks that the password saved in VCU matches the password saved in the RDF area.  If no
{   password is saved in the RDF the the VCU password is written to the RDF.  If there is no password in
{   VCU then nothing happens.  If the VCU password does not equal the RDF password then the system is stepped.

  PROCEDURE [XDCL] dsp$check_saved_passwords;

    VAR
      local_status: ost$status,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      rdf_password: t$password,
      rdf_password_data: t$rdf_password_data,
      rdf_password_data_seq_p: ^SEQ ( * ),
      vcu_password: t$password;

    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. ', ^local_status);
    IFEND;

    IF NOT password_data.password_initialized THEN
      RETURN;
    IFEND;

    rdf_password_data_seq_p := #SEQ (rdf_password_data);
    dsp$get_data_from_rdf (dsc$rdf_password_interval_data, dsc$rdf_production, rdf_password_data_seq_p);

    IF NOT rdf_password_data.password_initialized THEN
      rdf_password_data.password_initialized := TRUE;
      rdf_password_data.encrypted_password := password_data.encrypted_password;
      dsp$store_data_in_rdf (dsc$rdf_password_interval_data, dsc$rdf_production, #SEQ (rdf_password_data));
      RETURN;
    IFEND;

    vcu_password.encrypted_password := password_data.encrypted_password;
    change_password (FALSE, vcu_password);
    rdf_password.encrypted_password := rdf_password_data.encrypted_password;
    change_password (FALSE, rdf_password);

    IF vcu_password.password <> rdf_password.password THEN
      osp$fatal_system_error ('Operation Password mismatch, unauthorized entry, system aborted.', NIL);
    IFEND;

  PROCEND dsp$check_saved_passwords;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$force_lock_of_main_window', EJECT ??

{ PURPOSE:
{   This procedure forces the locking of the main window.  If the main window lock boolean in VCU is set then
{   the main window will be locked.

  PROCEDURE [XDCL, #GATE] dsp$force_lock_of_main_window;

    VAR
      local_status: ost$status,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * );

    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. ', ^local_status);
    IFEND;

    IF NOT password_data.password_initialized OR NOT password_data.lock_main_window THEN
      RETURN;
    IFEND;

    dpv$lock_main_window.window_id := dpv$system_core_display;
    dpv$lock_main_window.lock := TRUE;

  PROCEND dsp$force_lock_of_main_window;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$lock_unlock_main_window', EJECT ??

{ PURPOSE:
{   This procedure locks or unlocks the main window.
{ NOTE:
{  Osp$set_status_abnormal is used in this procedure so that the status variable contains the text.
{  One of the callers of this procedure displays the status text to the console.

  PROCEDURE [XDCL, #GATE] dsp$lock_unlock_main_window
    (    password: ost$name;
         lock_window: boolean;
     VAR status: ost$status);

    VAR
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      vcu_password: t$password;

    status.normal := TRUE;
    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      osp$set_status_abnormal (dsc$display_processor_id, dse$window_lock_not_allowed,
            'The locking of the main window is not allowed on this mainframe.', status);
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. ', ^status);
    IFEND;

    IF NOT password_data.password_initialized THEN
      osp$set_status_abnormal (dsc$display_processor_id, dse$no_password_exists,
            'This command can not be parsed until its associated password has been established.', status);
      RETURN;
    IFEND;

    vcu_password.encrypted_password := password_data.encrypted_password;
    change_password (FALSE, vcu_password);
    IF vcu_password.password <> password (1, 7) THEN
      osp$set_status_abnormal (dsc$display_processor_id, dse$invalid_password,
            'The password entered is invalid', status);
      RETURN;
    IFEND;

    password_data.lock_main_window := lock_window;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Problem accessing CDA area of CIP device. ', ^status);
    IFEND;

    dpv$lock_main_window.window_id := dpv$system_core_display;
    dpv$lock_main_window.lock := lock_window;

  PROCEND dsp$lock_unlock_main_window;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$lock_unlock_window_from_mtr', EJECT ??

{ PURPOSE:
{   This procedure is called from a signal handler which was triggered from the monitor commands used to
{   disable and enable the main operator window.

  PROCEDURE [XDCL, #GATE] dsp$lock_unlock_window_from_mtr
    (    signal_entry: dst$signal_contents_entry);

    VAR
      display_string: ost$string,
      identifier: ost$status_identifier,
      ignore_status: ost$status,
      integer_string: ost$string,
      number: ost$status_condition_number,
      password: ost$name,
      status: ost$status;

    password := signal_entry.luw_data.password;
    dsp$lock_unlock_main_window (password, signal_entry.luw_data.lock_window, status);
    IF NOT status.normal THEN
      osp$unpack_status_condition (status.condition, identifier, number);
      display_string.value := identifier;
      display_string.size := #SIZE (identifier) + 1;
      clp$convert_integer_to_string (number, 10, FALSE, integer_string, ignore_status);
      display_string.value (display_string.size, integer_string.size) := integer_string.value;
      display_string.size := display_string.size + integer_string.size + 1;
      display_string.value (display_string.size, * ) := status.text.value (1, status.text.size);
      display_string.size := display_string.size + status.text.size;
    ELSE
      IF signal_entry.luw_data.lock_window THEN
        display_string.value := 'The main operator window has been disabled.';
        display_string.size := 43;
      ELSE
        display_string.value := 'The main operator window has been enabled.';
        display_string.size := 42;
      IFEND;
    IFEND;
    dpp$put_critical_message (display_string.value (1, display_string.size), ignore_status);

  PROCEND dsp$lock_unlock_window_from_mtr;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$process_setoi_command', EJECT ??

{ PURPOSE:
{   This procedure is called from the system core command set_operation_interval (setoi).  It is used to set
{   the Operation Interval in VCU.  A password entered as a parameter must match the password in VCU before
{   the Interval can be changed.

  PROCEDURE [XDCL] dsp$process_setoi_command
    (    text: string ( * );
         id: dpt$window_id;
     VAR status: ost$status);

    VAR
      current_date_time: ost$date_time,
      current_frc: jmt$clock_time,
      display_string: string (osc$max_string_size),
      entered_date_time: ost$date_time,
      expiration_frc: jmt$clock_time,
      local_status: ost$status,
      loop_count: 0 .. 0ff(16),
      password: t$password,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      string_length: integer,
      token: t$token;

    status.normal := TRUE;
    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      dpp$put_next_line (id, 'WARNING -- The SETOI command is not allowed to be used on this mainframe.',
            local_status);
      RETURN;
    IFEND;

    IF syv$reading_dcfile THEN
      dpp$put_next_line (id, 'WARNING -- The SETOI command must be entered by an operator, not from a file.',
            local_status);
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Unable to read password data from CDA.', ^local_status);
    IFEND;

    IF NOT password_data.password_initialized THEN
      dpp$put_next_line (id, 'ERROR -- A SETOP command has NOT yet been entered, it must be', local_status);
      dpp$put_next_line (id, '         used before the SETOI command.', local_status);
      RETURN;
    IFEND;

    { Check that the user of the command has the authorization to use this command.

    password.encrypted_password := password_data.encrypted_password;
    change_password (FALSE, password);
    token.kind := c$tk_password_value;
    get_data (id, 'Enter the Operation Password:', '(it will not be displayed on the screen)', token);
    IF NOT token.retrieved THEN
      RETURN;
    IFEND;
    IF token.data.value (1, token.data.size) <> password.password THEN
      dpp$put_next_line (id, 'ERROR -- Invalid PASSWORD entered, it does not match the old PASSWORD saved.',
            local_status);
      dpp$put_next_line (id, '         The command has aborted. ', local_status);
      dpp$put_next_line (id, ' ', local_status);
      RETURN;
    IFEND;

    entered_date_time.hour := 0;
    entered_date_time.minute := 0;
    entered_date_time.second := 0;
    entered_date_time.millisecond := 0;

    loop_count := 3;

   /retrieve_interval/
    WHILE TRUE DO
      IF loop_count <= 0 THEN
        dpp$put_next_line (id, '         Allowable retries for the command exceeded, command aborted.',
              local_status);
        dpp$put_next_line (id, ' ', local_status);
        RETURN;
      ELSE
        loop_count := loop_count - 1;
      IFEND;

      token.kind := c$tk_integer_value;
      token.number.minimum := 1;

      token.number.maximum := 12;
      get_data (id, 'Enter the scheduled operation expiration MONTH:', ' ', token);
      IF NOT token.retrieved THEN
        RETURN;
      IFEND;
      entered_date_time.month := token.number.value;

      token.number.maximum := 31;
      get_data (id, 'Enter the scheduled operation expiration DAY:', ' ', token);
      IF NOT token.retrieved THEN
        RETURN;
      IFEND;
      entered_date_time.day := token.number.value;

      token.number.minimum := 1900;
      token.number.maximum := 2155;
      get_data (id, 'Enter the scheduled operation expiration YEAR:', ' ', token);
      IF NOT token.retrieved THEN
        RETURN;
      IFEND;
      entered_date_time.year := token.number.value - 1900;

      pmp$verify_compact_date (entered_date_time, local_status);
      IF NOT local_status.normal THEN
        dpp$put_next_line (id, 'ERROR -- The date entered is invalid, enter a correct date.', local_status);
        dpp$put_next_line (id, ' ', local_status);
        CYCLE /retrieve_interval/;
      IFEND;

      pmp$get_compact_date_time (current_date_time, local_status);
      pmp$get_microsecond_clock (current_frc, local_status);
      jmp$convert_date_time_dif_to_us (current_date_time, entered_date_time, current_frc, expiration_frc);
      IF expiration_frc <= current_frc THEN
        dpp$put_next_line (id, 'ERROR -- The date entered must be in the future.', local_status);
        dpp$put_next_line (id, ' ', local_status);
        CYCLE /retrieve_interval/;
      IFEND;

      token.kind := c$tk_yes_no_value;
      STRINGREP (display_string, string_length, 'Mainframe operation expiration scheduled for ',
            entered_date_time.month, '/', entered_date_time.day, '/', (1900 + entered_date_time.year));
      get_data (id, display_string (1, string_length), 'Is this date correct? (YES/NO)',
            token);
      IF NOT token.retrieved THEN
        RETURN;
      IFEND;
      IF token.data.value (1, token.data.size) = 'NO' THEN
        loop_count := 3;
        CYCLE /retrieve_interval/;
      IFEND;
      EXIT /retrieve_interval/;
    WHILEND /retrieve_interval/;

    password_data.interval_initialized := TRUE;
    password_data.interval_expired := FALSE;
    password_data.saved_current_frc := current_frc;
    password_data.expiration_frc := expiration_frc;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Unable to write password data to CDA.', ^local_status);
    IFEND;

    dpp$put_next_line (id, 'Parameter entry for the SETOI command has been completed.', local_status);
    dpp$put_next_line (id, ' ', local_status);

  PROCEND dsp$process_setoi_command;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$process_setop_command', EJECT ??

{ PURPOSE:
{   This procedure is called from the system core command set_operation_password (setop).  It is used to set
{   the Operation Password in VCU.  This command is only allowed to be used once, when the password data in
{   VCU is not initialized.

  PROCEDURE [XDCL] dsp$process_setop_command
    (    text: string ( * );
         id: dpt$window_id;
     VAR status: ost$status);

    VAR
      local_status: ost$status,
      loop_count: 0 .. 0ff(16),
      password: t$password,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      token: t$token;

    status.normal := TRUE;
    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      dpp$put_next_line (id, 'WARNING -- The SETOP command is not allowed to be used on this mainframe.',
            local_status);
      RETURN;
    IFEND;

    IF syv$reading_dcfile THEN
      dpp$put_next_line (id, 'WARNING -- The SETOP command must be entered by an operator, not from a file.',
            local_status);
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Unable to read password data from CDA.', ^local_status);
    IFEND;

    IF password_data.password_initialized THEN
      dpp$put_next_line (id, 'ERROR -- A SETOP command has already been entered.  Use the', local_status);
      dpp$put_next_line (id, '         CHAOP command after deadstart to change the password.', local_status);
      RETURN;
    IFEND;

    token.kind := c$tk_password_value;
    loop_count := 3;

   /retrieve_password/
    WHILE TRUE DO
      IF loop_count <= 0 THEN
        dpp$put_next_line (id, '         Allowable retries for the command exceeded, command aborted.',
              local_status);
        dpp$put_next_line (id, ' ', local_status);
        RETURN;
      ELSE
        loop_count := loop_count - 1;
      IFEND;

      get_data (id, 'Enter the Operation Password:', '(it will not be displayed on the screen)', token);
      IF NOT token.retrieved THEN
        RETURN;
      IFEND;
      password.password := token.data.value (1, token.data.size);
      get_data (id, 'Please reenter the password for confirmation:', ' ', token);
      IF NOT token.retrieved THEN
        RETURN;
      IFEND;
      IF token.data.value (1, token.data.size) <> password.password THEN
        dpp$put_next_line (id, 'ERROR -- The passwords do not match, try again.', local_status);
        dpp$put_next_line (id, ' ', local_status);
        CYCLE /retrieve_password/;
      IFEND;
      EXIT /retrieve_password/;
    WHILEND /retrieve_password/;
    change_password (TRUE, password);

    password_data.password_initialized := TRUE;
    password_data.encrypted_password := password.encrypted_password;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, local_status);
    IF NOT local_status.normal THEN
      syp$process_deadstart_status (' ', FALSE, local_status);
      osp$fatal_system_error ('Unable to write password data to CDA.', ^local_status);
    IFEND;

    dpp$put_next_line (id, 'Parameter entry for the SETOP command has been completed.', local_status);
    dpp$put_next_line (id, ' ', local_status);

  PROCEND dsp$process_setop_command;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$set_operation_interval', EJECT ??

{ PURPOSE:
{   This procedure changes the current operation interval that is stored in VCU.  It first checks that the
{   password parameter matches the password in VCU.  It also validates the date before saving the new data in
{   VCU.

  PROCEDURE [XDCL, #GATE] dsp$set_operation_interval
    (    password: ost$name;
         date_time: ost$date_time;
     VAR status: ost$status);

    VAR
      current_date_time: ost$date_time,
      current_frc: jmt$clock_time,
      expiration_frc: jmt$clock_time,
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      vcu_password: t$password;

    status.normal := TRUE;
    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      osp$set_status_condition (dse$command_not_allowed, status);
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Unable to read password data from CDA.', ^status);
    IFEND;

    IF NOT password_data.password_initialized THEN
      osp$set_status_condition (dse$no_password_exists, status);
      RETURN;
    IFEND;

    vcu_password.encrypted_password := password_data.encrypted_password;
    change_password (FALSE, vcu_password);
    IF vcu_password.password <> password (1, 7) THEN
      osp$set_status_condition (dse$invalid_password, status);
      RETURN;
    IFEND;

    pmp$verify_compact_date (date_time, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    pmp$get_compact_date_time (current_date_time, status);
    pmp$get_microsecond_clock (current_frc, status);
    jmp$convert_date_time_dif_to_us (current_date_time, date_time, current_frc, expiration_frc);
    IF expiration_frc <= current_frc THEN
      osp$set_status_condition (dse$invalid_interval_entered, status);
      RETURN;
    IFEND;

    password_data.interval_initialized := TRUE;
    password_data.interval_expired := FALSE;
    password_data.saved_current_frc := current_frc;
    password_data.expiration_frc := expiration_frc;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Unable to write password data to CDA.', ^status);
    IFEND;

  PROCEND dsp$set_operation_interval;
?? OLDTITLE ??
?? NEWTITLE := 'dsp$set_operation_password', EJECT ??

{ PURPOSE:
{   This procedure sets the operation password that is stored in VCU.

  PROCEDURE [XDCL, #GATE] dsp$set_operation_password
    (    password: ost$name;
     VAR status: ost$status);

    VAR
      index: 0 .. 0ff(16),
      password_data: dst$vcu_password_data,
      password_data_seq_p: ^SEQ ( * ),
      vcu_password: t$password;

    status.normal := TRUE;
    IF dsv$mainframe_type = dsc$mt_93x_mainframe THEN
      osp$set_status_condition (dse$command_not_allowed, status);
      RETURN;
    IFEND;

    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_read_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Unable to read password data from CDA.', ^status);
    IFEND;

    IF password_data.password_initialized THEN
      osp$set_status_condition (dse$password_exists, status);
      RETURN;
    IFEND;

    IF password (7) = ' ' THEN
      osp$set_status_condition (dse$seven_character_password, status);
      RETURN;
    IFEND;

    FOR index := 1 TO 7 DO
      IF NOT ((password (index) >= 'A') AND (password (index) <= 'Z')) AND
            NOT ((password (index) >= '0') AND (password (index) <= '9')) THEN
        osp$set_status_condition (dse$alphanumeric_password, status);
        RETURN;
      IFEND;
    FOREND;

    vcu_password.password := password (1, 7);
    change_password (TRUE, vcu_password);

    password_data.password_initialized := TRUE;
    password_data.encrypted_password := vcu_password.encrypted_password;
    password_data_seq_p := #SEQ (password_data);
    dsp$access_vcu_cda_data (dsc$vcu_write_access, dsc$vcu_password_data, password_data_seq_p, status);
    IF NOT status.normal THEN
      syp$process_deadstart_status (' ', FALSE, status);
      osp$fatal_system_error ('Unable to write password data to CDA.', ^status);
    IFEND;

  PROCEND dsp$set_operation_password;
?? OLDTITLE ??
MODEND dsm$manage_interval_password;
