?? RIGHT := 110 ??
?? TITLE := 'NOS/VE Job Initialization' ??
MODULE sym$job_initialization;
?? PUSH (LISTEXT := ON) ??
*copyc gft$file_desc_entry_p
*copyc gft$locked_file_desc_entry_p
*copyc mme$condition_codes
*copyc oss$job_fixed
?? POP ??
?? NEWTITLE := '  Externally-Declared Procedures and Variables', EJECT ??
*copyc pmf$job_mode
*copyc gfp$get_fde_p
*copyc gfp$get_sfid_from_fde_p
*copyc gfp$reassign_fde
*copyc gfp$scan_all_fdes
*copyc i#move
*copyc jmp$system_job
*copyc mmp$close_device_file
*copyc mmp$get_max_sdt_sdtx_pointer
*copyc mmp$mfh_for_segment_manager
*copyc mmp$open_file_by_sfid
*copyc osp$clear_mainframe_sig_lock
*copyc osp$set_mainframe_sig_lock
*copyc osp$system_error
*copyc pmp$zero_out_table
*copyc pmp$find_executing_task_xcb
*copyc jmv$jcb
*copyc jmv$kjlx_p
*copyc osv$mainframe_pageable_heap
*copyc syv$nosve_job_template
?? OLDTITLE ??
?? NEWTITLE := '  Global Types and Variables Declared by This Module', EJECT ??

  TYPE
    syt$initialize_array_entry = record
      sfid: gft$system_file_identifier,
      fde: gft$file_descriptor_entry,

      {If segment_specified, create it with same segment number and attributes.

      segment_specified: boolean,
      segment: ost$segment,
      sdt_entry: mmt$segment_descriptor,
      sdtx_entry: mmt$segment_descriptor_extended,
      p_data: ^array [0 .. * ] of cell,
      length: integer,
    recend;

  VAR
    syv$initialization_lock: [XDCL] ost$signature_lock := [0],
    syv$login_template: [XDCL] array [jmt$job_mode] of record
        number_of_clone_entries: integer,
        clone_entry_p: ^array [1 .. * ] of syt$initialize_array_entry,
      recend := [REP ($integer(uppervalue (jmt$job_mode)) + 1) OF [0, NIL]],
    syv$clone_enabled: [XDCL, #GATE] boolean := TRUE,
    syv$job_initialization_complete: [XDCL, #GATE, oss$job_fixed] boolean := FALSE;

?? OLDTITLE ??
?? NEWTITLE := '  PROCEDURE syp$initialize_job_mode', EJECT ??

  PROCEDURE [XDCL, #GATE] syp$initialize_job_mode;

    CONST
      max_clone_entries = 25;

    VAR
      check: integer,
      clone: integer,
      fde_p: gft$file_desc_entry_p,
      ignore_status: ost$status,
      ijlo: jmt$ijl_ordinal,
      job_mode: jmt$job_mode,
      login_table_entry_p: ^array [1 .. *] of syt$initialize_array_entry,
      scan_control: gft$scan_all_fdes_state,
      sdt_p: mmt$max_sdt_p,
      sdte_p: ^mmt$segment_descriptor,
      sdtx_p: mmt$max_sdtx_p,
      sdtxe_p: ^mmt$segment_descriptor_extended,
      segment_number: ost$segment,
      sfid_already_saved: boolean,
      system_file_id: gft$system_file_identifier,
      xcb_p: ^ost$execution_control_block;

    job_mode := pmf$job_mode ();
    IF syv$login_template [job_mode].clone_entry_p <> NIL THEN
      syv$job_initialization_complete := TRUE;
      RETURN;
    IFEND;

    IF job_mode <> jmc$batch THEN
      IF (job_mode <> jmc$interactive_connected) OR (NOT jmv$kjlx_p^ [jmv$jcb.job_id].timesharing_job) THEN
        syv$job_initialization_complete := TRUE;
        RETURN;
      IFEND;
    IFEND;

    IF (NOT syv$clone_enabled) OR (NOT syv$nosve_job_template) THEN
      syv$job_initialization_complete := TRUE;
      RETURN;
    IFEND;

    osp$set_mainframe_sig_lock (syv$initialization_lock);
    IF syv$login_template [job_mode].clone_entry_p <> NIL THEN
      osp$clear_mainframe_sig_lock (syv$initialization_lock);
      syv$job_initialization_complete := TRUE;
      RETURN;
    IFEND;

    IF jmp$system_job () THEN
      osp$clear_mainframe_sig_lock (syv$initialization_lock);
      syv$job_initialization_complete := TRUE;
      RETURN;
    IFEND;

    ALLOCATE login_table_entry_p: [1 .. max_clone_entries] IN osv$mainframe_pageable_heap^;
    pmp$zero_out_table (^login_table_entry_p^, #SIZE (login_table_entry_p^));

    pmp$find_executing_task_xcb (xcb_p);
    clone := 0;

{ Clone segments and open job_local files.  If this job has any attached permanent files, it never would have
{ entered this procedure in the first place.

    mmp$get_max_sdt_sdtx_pointer (xcb_p, sdt_p, sdtx_p);
    FOR segment_number := 0 TO xcb_p^.xp.segment_table_length DO
      sdte_p := ^sdt_p^.st [segment_number];
      IF sdte_p^.ste.vl <> osc$vl_invalid_entry THEN
        sdtxe_p := ^sdtx_p^.sdtx_table [segment_number];
        IF (NOT (mmc$sa_stack IN sdtxe_p^.software_attribute_set)) AND (sdtxe_p^.open_validating_ring_number
              <> 0) AND (segment_number <> osc$segnum_job_fixed_heap) THEN

          sfid_already_saved := FALSE;
          FOR check := 1 TO clone DO
            IF login_table_entry_p^ [check].sfid = sdtxe_p^.sfid THEN
              sfid_already_saved := TRUE;
            IFEND;
          FOREND;

          gfp$get_fde_p (sdtxe_p^.sfid, fde_p);
          IF (fde_p^.file_kind = gfc$fk_unnamed_file) OR (fde_p^.file_kind = gfc$fk_job_local_file) THEN
            clone := clone + 1;
            IF clone > max_clone_entries THEN
              osp$system_error ('Cannot create clone', NIL);
            IFEND;

            system_file_id := sdtxe_p^.sfid;
            login_table_entry_p^ [clone].segment_specified := TRUE;
            login_table_entry_p^ [clone].segment := segment_number;
            login_table_entry_p^ [clone].sfid := system_file_id;
            login_table_entry_p^ [clone].sdt_entry := sdte_p^;
            login_table_entry_p^ [clone].sdt_entry.ste.asid := 0;
            login_table_entry_p^ [clone].sdtx_entry := sdtxe_p^;
            login_table_entry_p^ [clone].sdtx_entry.assign_active := mmc$assign_active_null;
            login_table_entry_p^ [clone].fde := fde_p^;

            IF (NOT sfid_already_saved) AND (fde_p^.eoi_byte_address > 1) THEN
              ALLOCATE login_table_entry_p^ [clone].p_data: [0 .. fde_p^.eoi_byte_address - 1] IN
                    osv$mainframe_pageable_heap^;
              i#move (#ADDRESS (osc$os_ring_1, segment_number, 0), login_table_entry_p^ [clone].p_data,
                    fde_p^.eoi_byte_address);
              login_table_entry_p^ [clone].length := fde_p^.eoi_byte_address;
            ELSE
              login_table_entry_p^ [clone].length := 0;
            IFEND;

          ELSE

{ This check can't hurt.  If we get here, something has gone terribly wrong.  Crash.

            osp$system_error ('Job initialization error in SYP$INITIALIZE_JOB_MODE', NIL);
          IFEND;
        IFEND;
      IFEND;
    FOREND;

{ Clone unopened job_local files.

    gfp$scan_all_fdes (gfc$tr_job, scan_control, fde_p);
    WHILE fde_p <> NIL DO
    /search_file_descriptor_table/
      BEGIN
        gfp$get_sfid_from_fde_p (fde_p, system_file_id);
        IF fde_p^.file_kind <> gfc$fk_job_local_file THEN
          EXIT /search_file_descriptor_table/;
        IFEND;
        FOR check := 1 TO clone DO
          IF login_table_entry_p^ [check].sfid.file_entry_index = system_file_id.file_entry_index THEN
            EXIT /search_file_descriptor_table/;
          IFEND;
        FOREND;

        clone := clone + 1;
        IF clone > max_clone_entries THEN
          osp$system_error ('Cannot create clone', NIL);
        IFEND;
        login_table_entry_p^ [clone].segment_specified := FALSE;
        login_table_entry_p^ [clone].sfid := system_file_id;
        login_table_entry_p^ [clone].fde := fde_p^;

        IF fde_p^.eoi_byte_address > 0 THEN
          ALLOCATE login_table_entry_p^ [clone].p_data: [0 .. fde_p^.eoi_byte_address - 1] IN
                osv$mainframe_pageable_heap^;
          segment_number := 0;
          mmp$open_file_by_sfid (system_file_id, 1, 1, mmc$as_sequential, mmc$sar_write_extend,
                segment_number, ignore_status);
          i#move (#ADDRESS (osc$os_ring_1, segment_number, 0), login_table_entry_p^ [clone].p_data,
                fde_p^.eoi_byte_address);
          mmp$close_device_file (segment_number, ignore_status);
        IFEND;
        login_table_entry_p^ [clone].length := fde_p^.eoi_byte_address;
      END /search_file_descriptor_table/;

      gfp$scan_all_fdes (gfc$tr_null_residence, scan_control, fde_p);

    WHILEND;

    syv$job_initialization_complete := TRUE;
    syv$login_template [job_mode].clone_entry_p := login_table_entry_p;
    syv$login_template [job_mode].number_of_clone_entries := clone;
    osp$clear_mainframe_sig_lock (syv$initialization_lock);

  PROCEND syp$initialize_job_mode;
?? OLDTITLE ??
?? NEWTITLE := '  PROCEDURE syp$initialize_job' ??

  PROCEDURE [XDCL, #GATE] syp$initialize_job;

    VAR
      clone: integer,
      ignore_status: ost$status,
      job_mode: jmt$job_mode,
      max_segment_length: ost$segment_length,
      new_sfid: gft$system_file_identifier,
      sdt_p: mmt$max_sdt_p,
      sdte_p: ^mmt$segment_descriptor,
      sdtx_p: mmt$max_sdtx_p,
      sdtxe_p: ^mmt$segment_descriptor_extended,
      segment_number: ost$segment,
      xcb_p: ^ost$execution_control_block;


{ Note: IJL not yet set up - pmp$get_job_mode doesn't work

    job_mode := jmv$kjlx_p^ [jmv$jcb.job_id].job_mode;
    IF syv$login_template [job_mode].clone_entry_p = NIL THEN
      RETURN;
    IFEND;

    IF job_mode <> jmc$batch THEN
      IF (job_mode <> jmc$interactive_connected) OR (NOT jmv$kjlx_p^ [jmv$jcb.job_id].timesharing_job) THEN
        RETURN;
      IFEND;
    IFEND;

    IF (NOT syv$clone_enabled) OR (NOT syv$nosve_job_template) THEN
      RETURN;
    IFEND;

    pmp$find_executing_task_xcb (xcb_p);
    mmp$get_max_sdt_sdtx_pointer (xcb_p, sdt_p, sdtx_p);

    FOR clone := 1 TO syv$login_template [job_mode].number_of_clone_entries DO

      new_sfid := syv$login_template [job_mode].clone_entry_p^ [clone].sfid;
      gfp$reassign_fde (syv$login_template [job_mode].clone_entry_p^ [clone].sfid,
            ^syv$login_template [job_mode].clone_entry_p^ [clone].fde);
      IF NOT syv$login_template [job_mode].clone_entry_p^ [clone].segment_specified THEN
        IF syv$login_template [job_mode].clone_entry_p^ [clone].length > 0 THEN
          mmp$open_file_by_sfid (new_sfid, 1, 1, mmc$as_sequential, mmc$sar_write_extend,
                segment_number, ignore_status);
          i#move (syv$login_template [job_mode].clone_entry_p^ [clone].p_data, #ADDRESS (osc$os_ring_1,
                segment_number, 0), syv$login_template [job_mode].clone_entry_p^ [clone].length);
          mmp$close_device_file (segment_number, ignore_status);
        IFEND;
      ELSE {syv$login_template [job_mode].clone_entry_p^ [clone].segment_specified}
        segment_number := syv$login_template [job_mode].clone_entry_p^ [clone].segment;
        sdte_p := ^sdt_p^.st [segment_number];
        sdtxe_p := ^sdtx_p^.sdtx_table [segment_number];
        IF sdte_p^.ste.vl = osc$vl_invalid_entry THEN
          sdte_p^ := syv$login_template [job_mode].clone_entry_p^ [clone].sdt_entry;
          sdtxe_p^ := syv$login_template [job_mode].clone_entry_p^ [clone].sdtx_entry;
        ELSE
          sdtxe_p^.sfid.file_hash := syv$login_template [job_mode].clone_entry_p^ [clone].sdtx_entry.
                sfid.file_hash;
        IFEND;
        IF syv$login_template [job_mode].clone_entry_p^ [clone].length > 0 THEN
          i#move (syv$login_template [job_mode].clone_entry_p^ [clone].p_data, #ADDRESS (osc$os_ring_1,
                segment_number, 0), syv$login_template [job_mode].clone_entry_p^ [clone].length);
        IFEND;
      IFEND;
    FOREND;

    syv$job_initialization_complete := TRUE;

  PROCEND syp$initialize_job;
?? OLDTITLE, OLDTITLE ??
MODEND sym$job_initialization
