?? RIGHT := 110 ??
?? NEWTITLE := 'NOS/VE Deadstart : Install Deadstart File' ??
MODULE dsm$install_deadstart_file;

{ PURPOSE;
{   This module contains the procedures that deal with installing
{   and committing the disk based deadstart file.

?? PUSH (LISTEXT := ON) ??
*copyc dse$error_codes
*copyc fst$ansi_hdr1_label
*copyc fst$ansi_hdr2_label
*copyc fst$ansi_vol1_label
?? POP ??
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
*copyc amp$get_file_attributes
*copyc amp$get_segment_pointer
*copyc clp$convert_integer_to_rjstring
*copyc clp$convert_string_to_file_ref
*copyc clp$evaluate_parameters
*copyc clp$get_task_status
*copyc dsp$append_file_to_ds_file
*copyc dsp$check_system_available
*copyc dsp$complete_deadstart_file
*copyc dsp$get_integer_from_rdf
*copyc dsp$prep_ds_file_installation
*copyc dsp$store_integer_in_rdf
*copyc fsp$close_file
*copyc fsp$open_file
*copyc jmp$system_job
*copyc osp$set_status_abnormal
*copyc osp$verify_system_privilege
*copyc syp$display_deadstart_message
*copyc syp$process_deadstart_status
?? TITLE := 'Global Declarations Declared by This Module', EJECT ??

  VAR
    installation_interlocked: boolean := FALSE;

?? TITLE := 'dsp$commit_new_system', EJECT ??

{  PURPOSE:
{    This procedure sets a flag in the rdf_production area of the image
{    file to indicate that the disk based deadstart file PRIMARY mau
{    field should be updated to the value in the SECONDARY mau field
{    when appropriate.  The appropriate time is when a terminate_system
{    command has been entered after commit_new_system has been set to true.

  PROCEDURE [XDCL, #GATE] dsp$commit_new_system
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE commit_new_system, comns (
{ set_flag, sf: boolean = TRUE
{ status)

?? PUSH (LISTEXT := ON) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 3] of clt$pdt_parameter_name,
      parameters: array [1 .. 2] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        default_value: string (4),
      recend,
      type2: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [88, 4, 7, 12, 54, 28, 237],
    clc$command, 3, 2, 0, 0, 0, 0, 2, 'COMNS'], [
    ['SET_FLAG                       ',clc$nominal_entry, 1],
    ['SF                             ',clc$abbreviation_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 2]],
    [
{ PARAMETER 1
    [1, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_default_parameter, 0, 4],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$boolean_type],
    'TRUE'],
{ PARAMETER 2
    [[1, 0, clc$status_type]]];

?? POP ??

  CONST
    p$set_flag = 1,
    p$status = 2;

  VAR
    pvt: array [1 .. 2] of clt$parameter_value;

    VAR
      commit_new_dsfile: integer,
      task_name: ost$name,
      task_status: pmt$task_status;

    osp$verify_system_privilege;

    status.normal := TRUE;
    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    task_name := 'INSTALL_DS_CATALOG_TO_DISK';
    clp$get_task_status (task_name, task_status, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    IF NOT task_status.complete THEN
      syp$display_deadstart_message ('The COMMIT_NEW_SYSTEM command cannot be used until');
      syp$display_deadstart_message ('the ESTABLISH_DISK_BASED_SYSTEM command is finished.');
      syp$display_deadstart_message ('Please wait for the completion message.');
      osp$set_status_abnormal (dsc$display_processor_id, dse$estdbs_not_finished, '', status);
      RETURN;
    IFEND;

    dsp$check_system_available (status);
    IF NOT status.normal THEN
      IF pvt [p$set_flag].value^.boolean_value.value THEN
        syp$display_deadstart_message
              ('The following error occurred while attempting to commit the new system:');
        syp$process_deadstart_status ('Unable to commit new system', FALSE, status);
      ELSE
        syp$display_deadstart_message
              ('The following error occurred while attempting to decommit the new system:');
        syp$process_deadstart_status ('Unable to decommit new system', FALSE, status);
      IFEND;
      RETURN;
    IFEND;

    dsp$get_integer_from_rdf (dsc$rdf_commit_new_dsfile_flag, dsc$rdf_production, commit_new_dsfile);

    IF pvt [p$set_flag].value^.boolean_value.value THEN
      IF commit_new_dsfile = $INTEGER(FALSE) THEN
        dsp$store_integer_in_rdf (dsc$rdf_commit_new_dsfile_flag, dsc$rdf_production,
              $INTEGER (pvt [p$set_flag].value^.boolean_value.value));
        syp$display_deadstart_message ('New system will be committed at successful');
        syp$display_deadstart_message ('   completion of a terminate_system.');
      ELSE
        syp$display_deadstart_message ('New system has already been committed.');
      IFEND;
    ELSE
      IF commit_new_dsfile = $INTEGER(TRUE) THEN
        dsp$store_integer_in_rdf (dsc$rdf_commit_new_dsfile_flag, dsc$rdf_production,
              $INTEGER (pvt [p$set_flag].value^.boolean_value.value));
        syp$display_deadstart_message ('New system has been decommitted.');
      ELSE
        syp$display_deadstart_message ('New system has already been decommitted.');
      IFEND;
    IFEND;

  PROCEND dsp$commit_new_system;
?? TITLE := 'dsp$install_deadstart_file', EJECT ??

{  PURPOSE:
{    This procedure installs the disk based deadstart file.  It is called from the
{    establish_disk_based_system procedure.

  PROCEDURE [XDCL, #GATE] dsp$install_deadstart_file
    (    parameter_list: clt$parameter_list;
     VAR status: ost$status);

{ PROCEDURE install_deadstart_file, insdf (
{ deadstart_files, df: list of file = $required
{ status)

?? PUSH (LISTEXT := ON) ??

  VAR
    pdt: [STATIC, READ, cls$declaration_section] record
      header: clt$pdt_header,
      names: array [1 .. 3] of clt$pdt_parameter_name,
      parameters: array [1 .. 2] of clt$pdt_parameter,
      type1: record
        header: clt$type_specification_header,
        qualifier: clt$list_type_qualifier,
        element_type_spec: record
          header: clt$type_specification_header,
        recend,
      recend,
      type2: record
        header: clt$type_specification_header,
      recend,
    recend := [
    [1,
    [88, 4, 19, 15, 8, 26, 633],
    clc$command, 3, 2, 1, 0, 0, 0, 2, 'INSDF'], [
    ['DEADSTART_FILES                ',clc$nominal_entry, 1],
    ['DF                             ',clc$abbreviation_entry, 1],
    ['STATUS                         ',clc$nominal_entry, 2]],
    [
{ PARAMETER 1
    [1, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name, clc$specify_positionally],
    clc$pass_by_value, clc$immediate_evaluation, clc$standard_parameter_checking, 19, clc$required_parameter,
  0, 0],
{ PARAMETER 2
    [3, clc$normal_usage_entry, clc$non_secure_parameter,
    $clt$parameter_spec_methods[clc$specify_by_name],
    clc$pass_by_reference, clc$immediate_evaluation, clc$standard_parameter_checking, 3,
  clc$optional_parameter, 0, 0]],
{ PARAMETER 1
    [[1, 0, clc$list_type], [3, 1, clc$max_list_size, FALSE],
      [[1, 0, clc$file_type]]
    ],
{ PARAMETER 2
    [[1, 0, clc$status_type]]];

?? POP ??

  CONST
    p$deadstart_files = 1,
    p$status = 2;

  VAR
    pvt: array [1 .. 2] of clt$parameter_value;

    VAR
      attachment_options_p: ^fst$attachment_options,
      close_status: ost$status,
      deadstart_file: ost$name,
      file_attribute: ARRAY [1 .. 3] OF amt$get_item,
      file_identifier: amt$file_identifier,
      file_segment_p: amt$segment_pointer,
      header_1_label: fst$ansi_hdr1_label,
      header_2_label: fst$ansi_hdr2_label,
      ignore: boolean,
      interlock_set: boolean,
      list_p: ^clt$data_value,
      label_seq_p: ^SEQ ( * ),
      mau_file: ost$name,
      parsed_file_reference: fst$parsed_file_reference,
      temporary_string: string (8),
      volume_1_label: fst$ansi_vol1_label;

    status.normal := TRUE;
    clp$evaluate_parameters (parameter_list, #SEQ (pdt), NIL, ^pvt, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    IF NOT jmp$system_job () THEN
      RETURN;
    IFEND;

    {  Set the global interlock variable to ensure that the install deadstart file process is a
    {  serial process.

    interlock_set := FALSE;
    REPEAT
      IF NOT installation_interlocked THEN
        installation_interlocked := TRUE;
        interlock_set := TRUE;
      IFEND;
    UNTIL interlock_set;

  /global_interlock_set/
    BEGIN

      dsp$prep_ds_file_installation (deadstart_file, mau_file, status);
      IF NOT status.normal THEN
        EXIT /global_interlock_set/;
      IFEND;

      {  Initialize the header records.

      volume_1_label.label_identifier := 'VOL';
      volume_1_label.label_number := '1';
      header_1_label.label_identifier := 'HDR';
      header_1_label.label_number := '1';
      header_2_label.label_identifier := 'HDR';
      header_2_label.label_number := '2';

      {  Append the VOL1 header record to the system device deadstart file.

      label_seq_p := #SEQ (volume_1_label);
      dsp$append_file_to_ds_file (#SIZE(volume_1_label), deadstart_file, label_seq_p, status);
      IF NOT status.normal THEN
        EXIT /global_interlock_set/;
      IFEND;

      PUSH attachment_options_p: [1..1];
      attachment_options_p^ [1].selector := fsc$create_file;
      attachment_options_p^ [1].create_file := FALSE;
      file_attribute [1].key := amc$file_length;
      file_attribute [2].key := amc$block_type;
      file_attribute [3].key := amc$record_type;

      {  For each file in the deadstart files list, set up the HDR1 and HDR2 headers, append the
      {  headers to the system device deadstart file, then append the file to the system device
      {  deadstart file.

      list_p := pvt [p$deadstart_files].value;
      WHILE list_p <> NIL DO

        {  Store the required information in the HDR1 and HDR2 headers.

        clp$convert_string_to_file_ref (list_p^.element_value^.file_value^, parsed_file_reference, status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;
        header_1_label.file_identifier := parsed_file_reference.path (parsed_file_reference.last_name.index,
              parsed_file_reference.last_name.size);

        amp$get_file_attributes (list_p^.element_value^.file_value^, file_attribute, ignore, ignore,
              ignore, status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;

        clp$convert_integer_to_rjstring (file_attribute [1].file_length, 16, FALSE, '0', temporary_string,
              status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;
        header_2_label.block_length := temporary_string (1,5);
        header_2_label.ve_block_length_ext := temporary_string (6,3);
        IF file_attribute [2].block_type = amc$system_specified THEN
          header_2_label.ve_block_type := 'SS';
        ELSE
          header_2_label.ve_block_type := 'US';
        IFEND;
        IF file_attribute [3].record_type = amc$variable THEN
          header_2_label.ve_record_type := 'V';
        ELSE
          header_2_label.ve_record_type := 'U';
        IFEND;

        {  Append the HDR1 and HDR2 headers to the system device deadstart file.

        label_seq_p := #SEQ (header_1_label);
        dsp$append_file_to_ds_file (#SIZE(header_1_label), deadstart_file, label_seq_p, status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;
        label_seq_p := #SEQ (header_2_label);
        dsp$append_file_to_ds_file (#SIZE(header_2_label), deadstart_file, label_seq_p, status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;

        {  Append the file to the system device deadstart file.

        fsp$open_file (list_p^.element_value^.file_value^, amc$segment, attachment_options_p, NIL, NIL,
              NIL, NIL, file_identifier, status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;

      /file_open/
        BEGIN
          amp$get_segment_pointer (file_identifier, amc$sequence_pointer, file_segment_p, status);
          IF NOT status.normal THEN
            EXIT /file_open/;
          IFEND;
          dsp$append_file_to_ds_file (file_attribute [1].file_length, deadstart_file,
                file_segment_p.sequence_pointer, status);
          IF NOT status.normal THEN
            EXIT /file_open/;
          IFEND;
        END /file_open/;

        fsp$close_file (file_identifier, close_status);
        IF NOT status.normal THEN
          EXIT /global_interlock_set/;
        IFEND;
        IF NOT close_status.normal THEN
          status := close_status;
          EXIT /global_interlock_set/;
        IFEND;

        list_p := list_p^.link;
      WHILEND;

      {  Complete the install deadstart file process.

      dsp$complete_deadstart_file (deadstart_file, mau_file, status);

    END /global_interlock_set/;

    {  Clear the global interlock variable.

    installation_interlocked := FALSE;

  PROCEND dsp$install_deadstart_file;
MODEND dsm$install_deadstart_file;
