?? RIGHT := 110 ??
?? NEWTITLE := 'INSTALL_SOFTWARE Utility: RAP$DELETE_PREVIOUS_CYCLES Interface.' ??
MODULE ram$delete_previous_cycles;

{ PURPOSE:
{   This module contains the interface and procedures that delete previous
{   cycles of the installed products.
{
{ DESIGN:
{   The compiled module resides in RAF$LIBRARY.
{
{ NOTES:
{

?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Referenced by This Module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc rac$installation_cycles
*copyc rae$install_software_cc
*copyc rat$installation_control_record
*copyc rat$string
?? POP ??
*copyc amp$put_next
*copyc avp$ring_min
*copyc clp$convert_integer_to_string
*copyc clp$delete_variable
*copyc clp$get_variable
*copyc clp$include_file
*copyc clp$include_line
*copyc clp$trimmed_string_size
*copyc fsp$close_file
*copyc fsp$open_file
*copyc jmp$system_job
*copyc osp$append_status_file
*copyc osp$disestablish_cond_handler
*copyc osp$establish_block_exit_hndlr
*copyc osp$generate_log_message
*copyc osp$set_status_abnormal
*copyc pmp$get_unique_name
*copyc rap$clear_installation
*copyc rap$create_scl_status_variable
*copyc rap$convert_path_to_str
*copyc rap$get_cycle_data
*copyc rap$record_step_status
*copyc rap$record_subproduct_status
*copyc rap$sort_cycles

?? OLDTITLE ??
?? NEWTITLE := 'Global Declarations Declared by This Module', EJECT ??

  CONST
    delete_status_variable = 'RAV$DELETE_STATUS';

?? OLDTITLE ??
?? NEWTITLE := '[XDCL] rap$delete_previous_cycles', EJECT ??

{ PURPOSE:
{   This interface deletes previous cycles of the installed products.
{
{ DESIGN:
{   1.  When SAVE_PREVIOUS_CYCLES is specified false and a subproduct
{       installs completely (that is, through step 7), the lower file
{       cycles of that subproduct are deleted.
{
{      (It should be made clear that SAVE_PREVIOUS_CYCLES is not talking
{       about versions.  That it has no affect on version based
{       subproducts or, that when a subproduct changes file names or
{       paths from one version to the next, the previous files are not
{       found and therefore not removed.)
{
{   2.  An attempt is made to delete all lower file cycles belonging to a
{       subproduct.  When a file cycle cannot be deleted because it is
{       currently opened, the file cycle is added to a special delete job.
{
{   3.  The special delete job will be processed outside the INSS
{       environment.  Results are not recorded in the process summary file.
{       The processing of each file cycle in the delete job is as follows:
{
{       a.  Close the file cycle by: Removing file cycle from the command
{           list, if on command list.  Removing file cycle from the
{           library list, if on library list.  Detaching file cycle, if
{           attached.
{
{       b.  Delete the file cycle.
{
{       c.  Reattach the file cycle in the same way it was found.
{           (This will be implimented in the future.)
{
{   The failure of one subproduct will not jeopardize the remaining
{   subproducts.  Each subproduct is processed independently.
{
{ NOTES:
{   The deletion of extra file cycles works best if done in a batch job.
{   This is generally the case because of the nature of processing.  This
{   is not the case when the interactive mode is used.  However, this mode
{   is only used during deadstart when the execution of system jobs is
{   already restricted.
{
{   The SUBPRODUCT_FAILED_PROCESSING boolean has been initialized outside of
{   this interface and should never be re-initialized here.
{

  PROCEDURE [XDCL] rap$delete_previous_cycles
    (VAR installation_control_record {input, output} : rat$installation_control_record;
     VAR subproduct_failed_processing: boolean;
     VAR status: ost$status);


    VAR
      delete_job_file: ost$name,
      delete_job_fid: amt$file_identifier,
      errors_encountered: boolean,
      delete_job_file_opened: boolean,
      ignore_status: ost$status,
      local_status: ost$status,
      log_file: rat$path,
      processing_record: rat$subp_processing_record,
      subproduct_index: rat$subproduct_count,
      user_min_ring_str: ost$string;


?? NEWTITLE := 'abort_handler', EJECT ??

{ PURPOSE:
{   This procedure cleans up when an abort situation occurs within the
{   block structure.
{
{ DESIGN:
{   The function of this condition handler is to close the temporary
{   delete job file when an abort condition arises.
{
{ NOTES:
{

    PROCEDURE abort_handler
      (    condition: pmt$condition;
           condition_information: ^pmt$condition_information;
           save_area: ^ost$stack_frame_save_area;
       VAR handler_status: ost$status);

      VAR
        ignore_status: ost$status;

      fsp$close_file (delete_job_fid, ignore_status);

      purge_special_delete_job_file (delete_job_file (1, clp$trimmed_string_size (delete_job_file)),
            ignore_status);

    PROCEND abort_handler;

?? OLDTITLE, EJECT ??


    status.normal := TRUE;
    delete_job_file_opened := FALSE;

    IF NOT (rac$delete_previous_cycles_step IN installation_control_record.processing_header_p^.step_set) THEN
      RETURN;
    IFEND;

    rap$record_step_status (rac$delete_previous_cycles_step, rac$step_started, installation_control_record,
          status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    osp$establish_block_exit_hndlr (^abort_handler);

  /main/
    BEGIN

      get_delete_variables (installation_control_record, user_min_ring_str, delete_job_file, log_file,
            status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      { Create an SCL status variable to be used by the delete file command.

      rap$create_scl_status_variable (delete_status_variable, status);
      IF NOT status.normal THEN
        EXIT /main/;
      IFEND;

      FOR subproduct_index := 1 TO UPPERBOUND (installation_control_record.subproduct_processing_records_p^)
            DO
        processing_record := installation_control_record.subproduct_processing_records_p^
              [subproduct_index];

        IF (installation_control_record.job_identifier = processing_record.job_identifier) AND
              (rac$delete_previous_cycles_task IN processing_record.task_set) AND
              (processing_record.task_status <> rac$task_failed) THEN

          rap$record_subproduct_status (rac$delete_previous_cycles_task, rac$task_started, subproduct_index,
                installation_control_record, ignore_status);

          errors_encountered := FALSE;

          delete_previous_subp_cycles (processing_record.installation_catalog_p^, user_min_ring_str,
                log_file.path (1, log_file.size), installation_control_record.job_identifier, delete_job_file
                (1, clp$trimmed_string_size (delete_job_file)), delete_job_file_opened, delete_job_fid,
                processing_record.subproduct_info_pointers.element_list_p,
                processing_record.subproduct_info_pointers.subproduct_info_seq_p,
                installation_control_record.scratch_seq_p, errors_encountered);

          IF NOT errors_encountered THEN
            rap$record_subproduct_status (rac$delete_previous_cycles_task, rac$task_completed,
                  subproduct_index, installation_control_record, ignore_status);
          ELSE
            rap$record_subproduct_status (rac$delete_previous_cycles_task, rac$task_failed,
                  subproduct_index, installation_control_record, ignore_status);
            subproduct_failed_processing := TRUE;
          IFEND;

        IFEND;
      FOREND;

      IF delete_job_file_opened THEN
        submit_special_delete_job (delete_job_file (1, clp$trimmed_string_size (delete_job_file)),
              delete_job_fid, delete_job_file_opened, status);
        IF NOT status.normal THEN
          EXIT /main/;
        IFEND;
      IFEND;

      clp$delete_variable (delete_status_variable, ignore_status);

    END /main/;

    IF delete_job_file_opened THEN
      fsp$close_file (delete_job_fid, local_status);
      IF status.normal AND (NOT local_status.normal) THEN
        status := local_status;
      IFEND;

      purge_special_delete_job_file (delete_job_file (1, clp$trimmed_string_size (delete_job_file)),
            ignore_status);
    IFEND;

    osp$disestablish_cond_handler;

    rap$clear_installation (installation_control_record, ignore_status);

    rap$record_step_status (rac$delete_previous_cycles_step, rac$step_completed, installation_control_record,
          local_status);
    IF status.normal AND (NOT local_status.normal) THEN
      status := local_status;
    IFEND;

  PROCEND rap$delete_previous_cycles;

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

{ PURPOSE:
{   This procedure adds a file to the special delete job.  The delete job is
{   required for files that were open during the execution of the delete
{   previous cycles step and therefore could not be deleted.
{
{ DESIGN:
{   The special delete job is collected in a file.  If the file is not yet
{   opened, the file is opened and initialized.  In any case the required
{   SCL delete commands are added.
{
{   The user job name for the special delete job will be the job identifier
{   with the command abbreviation replaced by 'DELF'.
{
{ NOTES:
{

  PROCEDURE add_file_to_delete_job
    (    file_cycle_path: fst$file_reference;
         user_min_ring_str: ost$string;
         log_file: fst$file_reference;
         job_identifier: rat$job_identifier;
         delete_job_file: fst$file_reference;
     VAR delete_job_file_opened {input, output} : boolean;
     VAR delete_job_fid {input, output} : amt$file_identifier;
     VAR status: ost$status);


    VAR
      attachment_options: array [1 .. 3] of fst$attachment_option,
      ignore_byte_address: amt$file_byte_address,
      line: string (2000),
      line_length: integer,
      user_job_name: ost$name;


    status.normal := TRUE;

    IF NOT delete_job_file_opened THEN

      { Open the delete job file that will be used for building a special delete job.

      attachment_options [1].selector := fsc$access_and_share_modes;
      attachment_options [1].access_modes.selector := fsc$specific_access_modes;
      attachment_options [1].access_modes.value := $fst$file_access_options
            [fsc$read, fsc$shorten, fsc$append, fsc$modify];
      attachment_options [1].share_modes.selector := fsc$specific_share_modes;
      attachment_options [1].share_modes.value := $fst$file_access_options [];
      attachment_options [2].selector := fsc$create_file;
      attachment_options [2].create_file := TRUE;
      attachment_options [3].selector := fsc$wait_for_attachment;
      attachment_options [3].wait_for_attachment.wait := osc$wait;
      attachment_options [3].wait_for_attachment.wait_time := fsc$longest_wait_time;

      delete_job_file_opened := TRUE;
      fsp$open_file (delete_job_file, amc$record, ^attachment_options, NIL, NIL, NIL, NIL, delete_job_fid,
            status);
      IF NOT status.normal THEN
        delete_job_file_opened := FALSE;
        RETURN;
      IFEND;

      { Assemble the SCL commands that will initialize the delete job's processing.

      user_job_name := job_identifier;
      user_job_name (1, 4) := 'DELF';

      IF jmp$system_job () THEN

         { When the job is submitted from the system console, the system operator utility
         { must be entered in order to task to the minimum ring.  From the system console
         { the minimum ring is 3.  The only way to task to ring 3 is from inside the system
         { operator utility.
         {
         { The version of SOU that resides on the deadstart tape is invoked
         { rather than the $SYSTEM (osf$command_library) version.  This avoids
         { problems that may occur if the $SYSTEM version is obsolete.

?? FMT (FORMAT := OFF) ??
      STRINGREP (line, line_length,
           'JOB ujn=', user_job_name (1, clp$trimmed_string_size (user_job_name)),
           '      odi=', log_file (1, clp$trimmed_string_size (log_file)), ' jc=system; ',
           '  $system.osf$sou_library.system_operator_utility c=system_administration; ',
           '  TASK r=', user_min_ring_str.value (1, user_min_ring_str.size), '; ',
           '    VAR; ',
           '      delete_status: status; ',
           '      ignore_status: status; ',
           '    VAREND');
?? FMT (FORMAT := ON) ??

      ELSE { Job is not a system job. }

         { SYSTEM_OPERATOR_UTILITY is entered taking default capabilities.  The
         { current job could be a batch job that was originally submitted from the
         { console.  In that case tasking to ring 3 is still required.
         { ** This code needs to be updated.

?? FMT (FORMAT := OFF) ??
      STRINGREP (line, line_length,
           'JOB ujn=', user_job_name (1, clp$trimmed_string_size (user_job_name)),
           '      odi=', log_file (1, clp$trimmed_string_size (log_file)), '; ',
           '  $system.osf$sou_library.system_operator_utility; ',
           '  TASK r=', user_min_ring_str.value (1, user_min_ring_str.size), '; ',
           '    VAR; ',
           '      delete_status: status; ',
           '      ignore_status: status; ',
           '    VAREND');
?? FMT (FORMAT := ON) ??

      IFEND;

      amp$put_next (delete_job_fid, ^line, line_length, ignore_byte_address, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

    IFEND;

    { Add lines to delete the file to the end of the job file.

?? FMT (FORMAT := OFF) ??
    STRINGREP (line, line_length,
          '$system.delete_command_list_entry e=',
                 file_cycle_path (1, clp$trimmed_string_size (file_cycle_path)), ' status=ignore_status; ',
          '$system.set_program_attributes dl=',
                 file_cycle_path (1, clp$trimmed_string_size (file_cycle_path)), ' status=ignore_status; ',
          '$system.delete_file f=',
                 file_cycle_path (1, clp$trimmed_string_size (file_cycle_path)), ' status=delete_status; ',
          'IF NOT delete_status.normal THEN; ',
          '   display_value delete_status o=$job_log; ',
          'IFEND');
?? FMT (FORMAT := ON) ??

    amp$put_next (delete_job_fid, ^line, line_length, ignore_byte_address, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND add_file_to_delete_job;

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

{ PURPOSE:
{   This procedure deletes the low cycles of a file.
{
{ DESIGN:
{   An array of cycles for the file is obtained.  The cycles array is sorted
{   in decending order, so that makes the first entry the highest.
{
{   Deletion of a file requires that the delete command be executed at a
{   ring equal to or lower than ring 1 for the file.  To simplify processing
{   the procedure tasks down to the minimum ring of the user.
{
{   If a file cycle fails to delete because it is open it is added to the
{   special delete job.  Otherwise, the error is noted and processing
{   continues.
{
{ NOTES:
{   The scratch sequence is defined to be for temporary storage.
{   DELETE_PREVIOUS_FILE_CYCLES calls both RAP$GET_CYCLE_DATA and
{   GET_DELETE_STATUS, which inturn use the scratch sequence to store data.
{   To prevent GET_DELETE_STATUS from overwriting the cycle data a reset is
{   not performed here.  A reset is performed by RAP$GET_CYCLE_DATA.
{

  PROCEDURE delete_previous_file_cycles
    (    file_path: pft$path;
         user_min_ring_str: ost$string;
         log_file: fst$file_reference;
         job_identifier: rat$job_identifier;
         delete_job_file: fst$file_reference;
     VAR delete_job_file_opened {input, output} : boolean;
     VAR delete_job_fid {input, output} : amt$file_identifier;
     VAR scratch_seq_p {input} : ^SEQ ( * );
     VAR status: ost$status);


    VAR
      command_line: string (800),
      command_line_length: integer,
      cycle_number_str: ost$string,
      cycles_p: pft$p_cycle_array,
      delete_status: ost$status,
      file_cycle_path: fst$path,
      file_ref: rat$path,
      i: integer,
      ignore_status: ost$status,
      local_status: ost$status,
      password: pft$password;


    status.normal := TRUE;
    local_status.normal := TRUE;

    rap$get_cycle_data (file_path, scratch_seq_p, cycles_p, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    rap$sort_cycles (cycles_p);

    rap$convert_path_to_str (file_path, file_ref);
    file_cycle_path (1, * ) := file_ref.path (1, file_ref.size);
    file_cycle_path (file_ref.size + 1, * ) := '.';

    FOR i := 2 TO UPPERBOUND (cycles_p^) DO

      { Add the cycle number to the file path.

      clp$convert_integer_to_string (cycles_p^ [i].cycle_number, 10, FALSE, cycle_number_str, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      file_cycle_path (file_ref.size + 2, * ) := cycle_number_str.value (1, cycle_number_str.size);

      { Collect the SCL commands required to task down and delete the file cycle.

?? FMT (FORMAT := OFF) ??
    STRINGREP (command_line, command_line_length,
          delete_status_variable, '.normal = TRUE; ',
          'task r=', user_min_ring_str.value (1, user_min_ring_str.size), '; ',
          '  $system.delete_file f=', file_cycle_path (1, clp$trimmed_string_size (file_cycle_path)),
                   ' status=', delete_status_variable, '; ',
          'taskend');
?? FMT (FORMAT := ON) ??

      clp$include_line (command_line (1, command_line_length), TRUE, osc$null_name, status);
      IF NOT status.normal THEN
        RETURN;
      IFEND;

      get_delete_status (delete_status_variable, scratch_seq_p, delete_status);
      IF NOT delete_status.normal THEN
        IF delete_status.condition = ame$file_not_closed THEN
          add_file_to_delete_job (file_cycle_path, user_min_ring_str, log_file, job_identifier,
                delete_job_file, delete_job_file_opened, delete_job_fid, status);
          IF NOT status.normal THEN
            RETURN;
          IFEND;
        ELSE
          osp$generate_log_message ($pmt$ascii_logset [pmc$job_log], delete_status, ignore_status);
          osp$set_status_abnormal ('RA', rae$file_deletion_errors, '', status);
        IFEND;
      IFEND;

    FOREND;

  PROCEND delete_previous_file_cycles;

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

{ PURPOSE:
{   This procedure deletes the lower file cycles belonging to the files for
{   a subproduct.
{
{ DESIGN:
{   Determining what files belong to the subproduct is accomplished by
{   traversing the element list for the subproduct.  The traverse is
{   performed using recursion and each call to DELETE_PREVIOUS_SUBP_CYCLES
{   moves processing down to the next catalog level.
{
{   Both active and inactive elements are processed.
{
{ NOTES:
{   The scratch sequence is used by a subsequent procedure as temporary
{   storage for file information.
{

  PROCEDURE delete_previous_subp_cycles
    (    element_path: pft$path;
         user_min_ring_str: ost$string;
         log_file: fst$file_reference;
         job_identifier: rat$job_identifier;
         delete_job_file: fst$file_reference;
     VAR delete_job_file_opened {input, output} : boolean;
     VAR delete_job_fid {input, output} : amt$file_identifier;
     VAR element_p {input} : ^rat$element;
     VAR subproduct_info_seq_p {input} : ^rat$subproduct_info_sequence;
     VAR scratch_seq_p {input} : ^SEQ ( * );
     VAR errors_encountered: boolean);


    VAR
      current_element_path_p: ^pft$path,
      first_element_down_p: ^rat$element,
      i: integer,
      ignore_status: ost$status,
      local_status: ost$status;


    { The element_path parameter is the path for the current catalog.  Create
    { a PF format path array that is 1 larger than the size of the element
    { path.  This array will be used to construct the PF paths for the files
    { and subcatalogs that reside in the current catalog.

    PUSH current_element_path_p: [1 .. UPPERBOUND (element_path) + 1];
    FOR i := 1 TO UPPERBOUND (element_path) DO
      current_element_path_p^ [i] := element_path [i];
    FOREND;

    { Process the files and subcatalogs at the current catalog level.

    WHILE element_p <> NIL DO

      current_element_path_p^ [UPPERBOUND (current_element_path_p^)] := element_p^.name;

      IF element_p^.element_type = rac$file THEN

        delete_previous_file_cycles (current_element_path_p^, user_min_ring_str, log_file, job_identifier,
              delete_job_file, delete_job_file_opened, delete_job_fid, scratch_seq_p, local_status);
        IF NOT local_status.normal THEN
          IF local_status.condition <> rae$file_deletion_errors THEN
            osp$generate_log_message ($pmt$ascii_logset [pmc$job_log], local_status, ignore_status);
          IFEND;
          errors_encountered := TRUE;
        IFEND;

      ELSEIF (element_p^.element_type = rac$catalog) AND (element_p^.element_count <> 0) THEN

        first_element_down_p := #PTR (element_p^.first_element_down_p, subproduct_info_seq_p^);

        delete_previous_subp_cycles (current_element_path_p^, user_min_ring_str, log_file, job_identifier,
              delete_job_file, delete_job_file_opened, delete_job_fid, first_element_down_p,
              subproduct_info_seq_p, scratch_seq_p, errors_encountered);

      IFEND;

      element_p := #PTR (element_p^.next_element_across_p, subproduct_info_seq_p^);
    WHILEND;

  PROCEND delete_previous_subp_cycles;

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

{ PURPOSE:
{   This procedure returns the delete status variable.
{
{ DESIGN:
{
{ NOTES:
{   The scratch sequence is defined to be for temporary storage.
{   DELETE_PREVIOUS_FILE_CYCLES calls both RAP$GET_CYCLE_DATA and
{   GET_DELETE_STATUS, which inturn use the scratch sequence to store data.
{   To prevent GET_DELETE_STATUS from overwriting the cycle data a reset is
{   not performed here.  A reset is performed by RAP$GET_CYCLE_DATA.
{

  PROCEDURE get_delete_status
    (    delete_status_var_name: clt$variable_ref_expression;
     VAR scratch_seq_p: ^SEQ ( * );
     VAR delete_status: ost$status);


    VAR
      access_mode: clt$data_access_mode,
      class: clt$variable_class,
      evaluation_method: clt$expression_eval_method,
      delete_status_p: ^clt$data_value,
      type_specification_p: ^clt$type_specification;


    delete_status.normal := TRUE;

    clp$get_variable (delete_status_var_name, scratch_seq_p, class, access_mode, evaluation_method,
          type_specification_p, delete_status_p, delete_status);
    IF NOT delete_status.normal THEN
      RETURN;
    IFEND;

    delete_status := delete_status_p^.status_value^;

  PROCEND get_delete_status;

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

{ PURPOSE:
{   This procedure adds contains code for general setup of the delete process.
{
{ DESIGN:
{   The path to the job log is assembled.  The user's minimum ring is
{   obtained, as well as, a unique name for the special delete job file.
{
{ NOTES:
{

  PROCEDURE get_delete_variables
    (    installation_control_record: rat$installation_control_record;
     VAR user_min_ring_str: ost$string;
     VAR delete_job_file: ost$name;
     VAR log_file: rat$path;
     VAR status: ost$status);


    VAR
      installation_identifier: ost$name,
      installation_logs: rat$path,
      log_file_name: ost$name,
      user_minimum_ring: ost$ring;


    status.normal := TRUE;

    { Assemble the path to the job log file found under the installation identifier catalog.

    IF installation_control_record.job_status_record_p <> NIL THEN
      log_file_name := installation_control_record.job_status_record_p^.log_file_name;
    ELSE
      log_file_name := 'JOB_LOG';
    IFEND;

    installation_logs := installation_control_record.processing_header_p^.installation_defaults.
          installation_logs;
    installation_identifier := installation_control_record.processing_header_p^.installation_identifier;

    STRINGREP (log_file.path, log_file.size, installation_logs.path (1, installation_logs.size), '.',
          installation_identifier (1, clp$trimmed_string_size (installation_identifier)),
          '.', log_file_name (1, clp$trimmed_string_size (log_file_name)), '.$eoi');

    { Get the user's minimum ring for tasking purposes.

    user_minimum_ring := avp$ring_min ();
    clp$convert_integer_to_string (user_minimum_ring, 10, FALSE, user_min_ring_str, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    { Create a unique file name to be used for a special delete job if required.

    pmp$get_unique_name (delete_job_file, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

  PROCEND get_delete_variables;

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

{ PURPOSE:
{   This procedure purges the file used to build the special delete job file.
{
{ DESIGN:
{   The only reason this is a separate procedure is because it is called in
{   two places.
{
{ NOTES:
{

  PROCEDURE purge_special_delete_job_file
    (    delete_job_file: fst$file_reference;
     VAR status: ost$status);


    VAR
      command_line: string (800),
      command_line_length: integer;


    status.normal := TRUE;

    STRINGREP (command_line, command_line_length, '$system.delete_file f=', delete_job_file);

    clp$include_line (command_line (1, command_line_length), TRUE, osc$null_name, status);

  PROCEND purge_special_delete_job_file;

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

{ PURPOSE:
{   This procedure submits the special delete job.
{
{ DESIGN:
{   If the job is submitted from the system console, a 'QUIT' is added to the
{   delete job file to quit out of the system operator utility.  A 'JOBEND'
{   is also added to the delete job file.  The file is closed and submitted.
{   After the job is submitted the file is deleted.
{
{ NOTES:
{

  PROCEDURE submit_special_delete_job
    (    delete_job_file: fst$file_reference;
         delete_job_fid: amt$file_identifier;
     VAR delete_job_file_opened: boolean;
     VAR status: ost$status);


    VAR
      ignore_byte_address: amt$file_byte_address,
      ignore_status: ost$status,
      line: rat$string;


    status.normal := TRUE;

    { Assemble the SCL commands to complete the special cased deletion job.

    IF jmp$system_job () THEN

         { If the job was submitted from the system console, the system operator
         { utility was entered.  A QUIT is added to the job to exit the system
         { operator utility.

?? FMT (FORMAT := OFF) ??
      STRINGREP (line.value, line.length,
           '  TASKEND; ',
           '  QUIT; ',
           'JOBEND');
?? FMT (FORMAT := ON) ??

    ELSE  { Job is not a system job. }

         { SYSTEM_OPERATOR_UTILITY was entered.  A QUIT is needed
         { here as well.  ** This code needs to be updated.

?? FMT (FORMAT := OFF) ??
      STRINGREP (line.value, line.length,
           '  TASKEND; ',
           '  QUIT; ',
           'JOBEND');
?? FMT (FORMAT := ON) ??

    IFEND;

    amp$put_next (delete_job_fid, ^line.value, line.length, ignore_byte_address, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;

    fsp$close_file (delete_job_fid, status);
    IF NOT status.normal THEN
      RETURN;
    IFEND;
    delete_job_file_opened := FALSE;

    clp$include_file (delete_job_file, '', osc$null_name, status);

    purge_special_delete_job_file (delete_job_file, ignore_status);

  PROCEND submit_special_delete_job;
MODEND ram$delete_previous_cycles;
