?? RIGHT := 110 ??
?? NEWTITLE := 'NAM$INTERNAL_CONNECTION_MGMT' ??
MODULE nam$internal_connection_mgmt;
?? RIGHT := 110 ??
?? PUSH (LISTEXT := ON) ??
*copyc fst$file_reference
*copyc jmt$system_supplied_name
*copyc jmv$executing_within_system_job
*copyc nae$application_interfaces
*copyc nae$directory_me_conditions
*copyc nae$namve_conditions
*copyc nat$application_name
*copyc nat$directory_interfaces
*copyc nat$client_attributes
*copyc nat$create_attributes
*copyc nat$get_attributes
*copyc nat$server_attributes
*copyc nat$switched_connection
*copyc nat$wait_time
*copyc ost$i_wait
?? POP ??
?? TITLE := 'XREFd PROCEDURES', EJECT ??
*copyc amp$return
*copyc baf$task_file_entry_p
*copyc nap$clear_switch_offer
*copyc nap$create_network_file
*copyc nap$get_connection_identifier
*copyc nap$namve_system_error
*copyc nap$remove_wait_data_available
*copyc nap$remove_wait_server_response
*copyc nap$se_request_connection
*copyc nap$set_switch_offer
*copyc nap$se_terminate_connection
*copyc nlp$end_title_translation
*copyc nlp$sk_lock_job_socket
*copyc nlp$sk_tcp_remove_accept_socket
*copyc nlp$sk_tcp_remove_data_avail
*copyc nlp$sk_tcp_remove_clear_to_send
*copyc nlp$sk_remove_wait_socket_offer
*copyc nlp$sk_unlock_job_socket
*copyc nlp$translate_title
*copyc nlp$udp_remove_clear_to_send
*copyc nlp$udp_remove_data_available
*copyc osp$is_caller_system_privileged
*copyc osp$pop_inhibit_job_recovery
*copyc osp$push_inhibit_job_recovery
*copyc osp$set_status_abnormal
*copyc osp$set_status_condition
*copyc pmp$get_job_names
*copyc pmp$log_ascii
*copyc pmp$ready_task
*copyc pmp$get_executing_task_gtid
?? TITLE := 'GLOBAL VARIABLES', EJECT ??
*copyc oss$job_paged_literal
*copyc nav$network_paged_heap
*copyc nav$namve_active
*copyc nav$client_attributes_list
*copyc nav$server_attributes_list
*copyc nav$switched_connections_list

  VAR
    end_directory_search: [READ, oss$job_paged_literal] string (20) := 'NAP$END_DIRECTORY_SEARCH';

?? TITLE := 'NAP$BEGIN_DIRECTORY_SEARCH', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$begin_directory_search
    (    title_pattern: nat$title_pattern;
         client: nat$application_name;
         recurrent_search: boolean;
     VAR search_identifier: nat$directory_search_identifier;
     VAR status: ost$status);

*copyc nah$begin_directory_search

    VAR
      client_attributes: ^nat$client_attributes,
      index: integer,
      search_domain: nat$title_domain,
      wild_card: boolean,
      wild_card_characters: [STATIC, READ, oss$job_paged_literal] set of char := ['?', '*', '''', '[', ']'];

    IF NOT nav$namve_active THEN
      osp$set_status_condition (nae$network_inactive, status);
      RETURN; {----->
    IFEND;

    status.normal := TRUE;
    osp$push_inhibit_job_recovery;
    osp$begin_subsystem_activity;
    nlp$get_nonexclusive_access (nav$client_attributes_list.access_control);
    nap$find_client_attributes (client, client_attributes);
    IF client_attributes = NIL THEN
      osp$set_status_abnormal (nac$status_id, nae$unknown_application, client, status);
    ELSE
      nlp$get_nonexclusive_access (client_attributes^.access_control);
      nap$validate_user (client_attributes^.client_capability, client_attributes^.client_ring,
            client_attributes^.client_system_privilege, status);
      IF NOT status.normal THEN
{ Client not authorized for this request.
        osp$set_status_abnormal (nac$status_id, nae$unknown_application, client, status);
      ELSEIF client_attributes^.client_status = nac$application_inactive THEN
        osp$set_status_abnormal (nac$status_id, nae$application_inactive, client, status);
      ELSE
        #SCAN (wild_card_characters, title_pattern, index, wild_card);
        search_domain.kind := nac$catenet_domain;
        nlp$translate_title (title_pattern, wild_card, client_attributes^.protocol, recurrent_search,
              search_domain, nac$cdna_external, search_identifier, status);
      IFEND;

      nlp$release_nonexclusive_access (client_attributes^.access_control);
    IFEND;

    nlp$release_nonexclusive_access (nav$client_attributes_list.access_control);
    osp$end_subsystem_activity;
    osp$pop_inhibit_job_recovery;

  PROCEND nap$begin_directory_search;
?? TITLE := 'NAP$CHECK_CONNECTION', EJECT ??

  PROCEDURE [XDCL] nap$check_connection
    (    server: nat$application_name;
     VAR activity_complete: boolean;
     VAR status: ost$status);

    VAR
      assigned_connection: ^nat$server_connection_attribute,
      executing_job_name: jmt$system_supplied_name,
      executing_taskid: ost$global_task_id,
      ignore_status: ost$status,
      previous_wait_for_connection: ^^nat$wait_for_connection,
      server_attributes: ^nat$server_attributes,
      server_job_attributes: ^nat$server_job_attributes,
      task_in_wait_queue: boolean,
      user_supplied_name: jmt$user_supplied_name,
      wait_for_connection: ^nat$wait_for_connection;

    status.normal := TRUE;
    activity_complete := FALSE;
    task_in_wait_queue := FALSE;
    pmp$get_executing_task_gtid (executing_taskid);
    pmp$get_job_names (user_supplied_name, executing_job_name, ignore_status);

    osp$push_inhibit_job_recovery;
    osp$begin_subsystem_activity;
    nlp$get_nonexclusive_access (nav$server_attributes_list.access_control);
    nap$find_server_attributes (server, server_attributes);
    IF server_attributes = NIL THEN
{ Unknown server.
      activity_complete := TRUE;
    ELSE
      nlp$get_exclusive_access (server_attributes^.access_control);
      IF server_attributes^.server_status = nac$application_inactive THEN
        activity_complete := TRUE;
      ELSE
        server_job_attributes := server_attributes^.server_job_list;
        WHILE (server_job_attributes <> NIL) AND (server_job_attributes^.job_name <> executing_job_name) DO
          server_job_attributes := server_job_attributes^.next_entry;
        WHILEND;

        IF server_job_attributes = NIL THEN
{ Server not attached.
          activity_complete := TRUE;
        ELSE
{ Check if the task is queued in the wait_for_connection queue.

          wait_for_connection := server_attributes^.wait_for_connection;
          previous_wait_for_connection := ^server_attributes^.wait_for_connection;
          WHILE (wait_for_connection <> NIL) AND (wait_for_connection^.job_name <> executing_job_name) DO
            previous_wait_for_connection := ^wait_for_connection^.next_entry;
            wait_for_connection := wait_for_connection^.next_entry;
          WHILEND;

          IF (wait_for_connection <> NIL) AND (wait_for_connection^.task_id <> executing_taskid) THEN
            activity_complete := TRUE;
            osp$set_status_condition (nae$multiple_waits_attempted, status);
          IFEND;

          IF status.normal THEN
            task_in_wait_queue := wait_for_connection <> NIL;

{ Check if a connection is available.

            IF server_attributes^.assigned_connections_list <> NIL THEN
              activity_complete := TRUE;
              IF task_in_wait_queue THEN
{ Remove task from the wait_for_connection queue.
                previous_wait_for_connection^ := wait_for_connection^.next_entry;
                FREE wait_for_connection IN nav$network_paged_heap^;
              IFEND;
            ELSE
              IF NOT task_in_wait_queue THEN
{ Queue task in the wait_for_connection queue.
                REPEAT
                  ALLOCATE wait_for_connection IN nav$network_paged_heap^;
                  IF wait_for_connection = NIL THEN
                    osp$end_subsystem_activity;
                    syp$cycle;
                    osp$begin_subsystem_activity;
                  IFEND;
                UNTIL wait_for_connection <> NIL;
                wait_for_connection^.task_id := executing_taskid;
                wait_for_connection^.job_name := executing_job_name;
                wait_for_connection^.next_entry := server_attributes^.wait_for_connection;
                server_attributes^.wait_for_connection := wait_for_connection;
              IFEND;
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      nlp$release_exclusive_access (server_attributes^.access_control);
    IFEND;

    nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);
    osp$end_subsystem_activity;
    osp$pop_inhibit_job_recovery;

  PROCEND nap$check_connection;
?? TITLE := 'NAP$CHECK_SWITCH_ACCEPT', EJECT ??

  PROCEDURE [XDCL] nap$check_switch_accept
    (    file: fst$file_reference;
     VAR activity_complete: boolean;
     VAR status: ost$status);

    VAR
      executing_taskid: ost$global_task_id,
      connection_id: nat$connection_id,
      ignore_status: ost$status,
      previous_switched_connection: ^^nat$switched_connection,
      switched_connection: ^nat$switched_connection;

    activity_complete := FALSE;
    status.normal := TRUE;
    nap$get_connection_identifier (file, connection_id, status);
    IF status.normal THEN
      osp$push_inhibit_job_recovery;
      nlp$get_exclusive_access (nav$switched_connections_list.access_control);
      switched_connection := nav$switched_connections_list.switched_connection;
      previous_switched_connection := ^nav$switched_connections_list.switched_connection;

      WHILE (switched_connection <> NIL) AND (switched_connection^.connection_id <> connection_id) DO
        previous_switched_connection := ^switched_connection^.next_entry;
        switched_connection := switched_connection^.next_entry;
      WHILEND;

      IF switched_connection = NIL THEN
        activity_complete := TRUE;
        osp$set_status_abnormal (nac$status_id, nae$no_switch_offer_pending, file, status);
      ELSEIF switched_connection^.switch_status = nac$switch_complete THEN
        activity_complete := TRUE;
        previous_switched_connection^ := switched_connection^.next_entry;
        nap$clear_switch_offer (file, TRUE, ignore_status);
        FREE switched_connection IN nav$network_paged_heap^;
      ELSE
        pmp$get_executing_task_gtid (executing_taskid);
        IF switched_connection^.wait_for_switch_accept.index = 0 THEN

{ ** It is assumed that only one task will be allowed to wait for switch accept.

          switched_connection^.wait_for_switch_accept := executing_taskid;
        ELSEIF switched_connection^.wait_for_switch_accept <> executing_taskid THEN
          osp$set_status_abnormal (nac$status_id, nae$multiple_waits_attempted, 'SWITCH ACCEPT', status);
        IFEND;
      IFEND;

      nlp$release_exclusive_access (nav$switched_connections_list.access_control);
      osp$pop_inhibit_job_recovery;

    ELSEIF (NOT status.normal) AND (status.condition = nae$system_interrupt) THEN
      status.normal := TRUE;
    IFEND;

  PROCEND nap$check_switch_accept;
?? TITLE := 'NAP$CHECK_SWITCH_OFFER', EJECT ??

  PROCEDURE [XDCL] nap$check_switch_offer
    (    source: jmt$system_supplied_name;
     VAR activity_complete: boolean;
     VAR status: ost$status);

    VAR
      executing_taskid: ost$global_task_id,
      executing_job_name: jmt$system_supplied_name,
      ignore_status: ost$status,
      previous_wait_for_switch_offer: ^^nat$wait_for_switch_offer,
      switched_connection: ^nat$switched_connection,
      task_in_wait_queue: boolean,
      user_supplied_name: jmt$user_supplied_name,
      wait_for_switch_offer: ^nat$wait_for_switch_offer;

    status.normal := TRUE;
    activity_complete := FALSE;
    task_in_wait_queue := FALSE;
    pmp$get_executing_task_gtid (executing_taskid);
    osp$push_inhibit_job_recovery;
    nlp$get_exclusive_access (nav$switched_connections_list.access_control);
    pmp$get_job_names (user_supplied_name, executing_job_name, ignore_status);

{ Check if the current task is in the wait_for_switch_offer queue.

    wait_for_switch_offer := nav$switched_connections_list.wait_for_switch_offer;
    previous_wait_for_switch_offer := ^nav$switched_connections_list.wait_for_switch_offer;

    WHILE (wait_for_switch_offer <> NIL) AND (wait_for_switch_offer^.destination_job_name <>
          executing_job_name) DO
      previous_wait_for_switch_offer := ^wait_for_switch_offer^.next_entry;
      wait_for_switch_offer := wait_for_switch_offer^.next_entry;
    WHILEND;

    IF (wait_for_switch_offer <> NIL) AND (wait_for_switch_offer^.destination_task_id <> executing_taskid)
          THEN
      activity_complete := TRUE;
      osp$set_status_abnormal (nac$status_id, nae$multiple_waits_attempted, 'SWITCH OFFER', status);
    IFEND;

    IF status.normal THEN
      task_in_wait_queue := wait_for_switch_offer <> NIL;

{ Check if a switch offer has been made.

      switched_connection := nav$switched_connections_list.switched_connection;

      WHILE (switched_connection <> NIL) AND ((switched_connection^.source_job_name <> source) OR
            (switched_connection^.destination_job_name <> executing_job_name) OR
            (switched_connection^.switch_status = nac$switch_complete)) DO
        switched_connection := switched_connection^.next_entry;
      WHILEND;

      IF switched_connection <> NIL THEN
        activity_complete := TRUE;
        IF task_in_wait_queue THEN
{ Remove the entry in the wait_for_switch_offer queue.
          previous_wait_for_switch_offer^ := wait_for_switch_offer^.next_entry;
          FREE wait_for_switch_offer IN nav$network_paged_heap^;
        IFEND;
      ELSE
{ Queue the task in the wait_for_switch_offer list.

        IF NOT task_in_wait_queue THEN
          REPEAT
            ALLOCATE wait_for_switch_offer IN nav$network_paged_heap^;
            IF wait_for_switch_offer = NIL THEN
              syp$cycle;
            IFEND;
          UNTIL wait_for_switch_offer <> NIL;
          wait_for_switch_offer^.source_job_name := source;
          wait_for_switch_offer^.destination_job_name := executing_job_name;
          wait_for_switch_offer^.destination_task_id := executing_taskid;
          wait_for_switch_offer^.next_entry := nav$switched_connections_list.wait_for_switch_offer;
          nav$switched_connections_list.wait_for_switch_offer := wait_for_switch_offer;
        IFEND;
      IFEND;
    IFEND;

    nlp$release_exclusive_access (nav$switched_connections_list.access_control);
    osp$pop_inhibit_job_recovery;

  PROCEND nap$check_switch_offer;
?? TITLE := 'NAP$CANCEL_SWITCH_OFFER', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$cancel_switch_offer
    (    file: fst$file_reference;
     VAR status: ost$status);

    VAR
      connection_id: nat$connection_id,
      switch_complete: boolean,
      ignore_status: ost$status;

    status.normal := TRUE;
    nap$get_connection_identifier (file, connection_id, status);
    IF status.normal THEN
      nlp$cancel_switch_offer (connection_id, switch_complete, status);
      IF status.normal THEN
        nap$clear_switch_offer (file, switch_complete, ignore_status);
        IF switch_complete THEN
          osp$set_status_abnormal (nac$status_id, nae$switch_offer_accepted, file, status);
        IFEND;
      IFEND;
    ELSEIF (NOT status.normal) AND (status.condition = nae$system_interrupt) THEN
{
{ The variable switch_complete is unset.  It is just used as a place holder.
{
      nap$clear_switch_offer (file, switch_complete, ignore_status);
      status.normal := TRUE;
    IFEND;

  PROCEND nap$cancel_switch_offer;
?? TITLE := 'NAP$END_DIRECTORY_SEARCH', EJECT ??

  PROCEDURE [XDCL, #GATE] nap$end_directory_search
    (    search_identifier: nat$directory_search_identifier;
     VAR status: ost$status);

*copyc nah$end_directory_search

    status.normal := TRUE;
    nlp$end_title_translation (search_identifier, status);
    IF (NOT status.normal) AND (status.condition = nae$translation_req_not_active) THEN
      osp$set_status_abnormal (nac$status_id, nae$invalid_directory_search_id, end_directory_search, status);
    IFEND;

  PROCEND nap$end_directory_search;
?? TITLE := 'NAP$MONITOR_SERVER_CONNECTIONS', EJECT ??

  PROCEDURE [XDCL] nap$monitor_server_connections
    (    current_time: integer);

{  CONST
{    expiration_interval = 300000000; {5 min in micro sec}

    VAR
      nav$connection_mgmt_expir_int: [XREF] integer,
      nav$assigned_conn_timeout_count: [XREF] integer,
      nav$server_not_attach_count: [XREF] integer;

    VAR
      assigned_connection: ^nat$server_connection_attribute,
      connection_released: boolean,
      ignore_status: ost$status,
      next_server_attributes: ^nat$server_attributes,
      previous_assigned_connection: ^^nat$server_connection_attribute,
      previous_job_attributes: ^^nat$server_job_attributes,
      server_job_attributes: ^nat$server_job_attributes,
      server_attributes: ^nat$server_attributes;

    { Scan the assigned connections list for expired unacquired connections.
    nlp$get_nonexclusive_access (nav$server_attributes_list.access_control);
    server_attributes := nav$server_attributes_list.server_attributes;

    WHILE server_attributes <> NIL DO
      nlp$get_exclusive_access (server_attributes^.access_control);
      assigned_connection := server_attributes^.assigned_connections_list;
      previous_assigned_connection := ^server_attributes^.assigned_connections_list;

      WHILE assigned_connection <> NIL DO
        IF (assigned_connection^.time_stamp + nav$connection_mgmt_expir_int) <= current_time THEN
          previous_assigned_connection^ := assigned_connection^.next_entry;
          nap$se_terminate_connection (assigned_connection^.connection_id, nac$connection_failed, FALSE,
                connection_released, ignore_status);
          IF assigned_connection^.directed_connection THEN
            decrement_assigned_conn_count (server_attributes, assigned_connection^.job_name);
          IFEND;

          FREE assigned_connection IN nav$network_paged_heap^;
          server_attributes^.connection_count := server_attributes^.connection_count - 1;
{ *** DEBUG}
          pmp$log_ascii ('AM - Assigned connection timeout.', $pmt$ascii_logset [pmc$system_log],
                pmc$msg_origin_program, ignore_status);
          assigned_connection := previous_assigned_connection^;
        ELSE
          previous_assigned_connection := ^assigned_connection^.next_entry;
          assigned_connection := assigned_connection^.next_entry;
        IFEND;
      WHILEND;


      { Scan server_attributes_list for unsigned on job entries.

      server_job_attributes := server_attributes^.server_job_list;
      previous_job_attributes := ^server_attributes^.server_job_list;
      WHILE server_job_attributes <> NIL DO
        IF (server_job_attributes^.job_status = nac$server_job_initiated) AND
              ((server_job_attributes^.time_stamp + nav$connection_mgmt_expir_int) <= current_time) THEN
          previous_job_attributes^ := server_job_attributes^.next_entry;
          FREE server_job_attributes IN nav$network_paged_heap^;
          { *** DEBUG}
          pmp$log_ascii ('AM - Initiated job did not attach to server.', $pmt$ascii_logset [pmc$system_log],
                pmc$msg_origin_program, ignore_status);
          server_job_attributes := previous_job_attributes^;
        ELSE
          previous_job_attributes := ^server_job_attributes^.next_entry;
          server_job_attributes := server_job_attributes^.next_entry;
        IFEND;
      WHILEND;

      next_server_attributes := server_attributes^.next_entry;
      nlp$release_exclusive_access (server_attributes^.access_control);
      server_attributes := next_server_attributes;
    WHILEND;

    nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);

  PROCEND nap$monitor_server_connections;
?? TITLE := 'NAP$PROCESS_TASK_TERMINATION', EJECT ??

  PROCEDURE [XDCL] nap$process_task_termination;

{ The purpose of this procedure is to remove the terminating task from the
{ wait_for_switch_offer queues.

    VAR
      executing_taskid: ost$global_task_id,
      local_status: ost$status,
      previous_wait_for_connection: ^^nat$wait_for_connection,
      previous_wait_for_switch_offer: ^^nat$wait_for_switch_offer,
      wait_for_connection: ^nat$wait_for_connection,
      wait_for_switch_offer: ^nat$wait_for_switch_offer;

    pmp$get_executing_task_gtid (executing_taskid);
    osp$push_inhibit_job_recovery;
    nlp$get_exclusive_access (nav$switched_connections_list.access_control);

{ Check if the task had been waiting for switched connections.

    wait_for_switch_offer := nav$switched_connections_list.wait_for_switch_offer;
    previous_wait_for_switch_offer := ^nav$switched_connections_list.wait_for_switch_offer;
    WHILE (wait_for_switch_offer <> NIL) AND (wait_for_switch_offer^.destination_task_id <> executing_taskid)
          DO
      previous_wait_for_switch_offer := ^wait_for_switch_offer^.next_entry;
      wait_for_switch_offer := wait_for_switch_offer^.next_entry;
    WHILEND;

    IF wait_for_switch_offer <> NIL THEN
      previous_wait_for_switch_offer^ := wait_for_switch_offer^.next_entry;
      FREE wait_for_switch_offer IN nav$network_paged_heap^;
    IFEND;

    nlp$release_exclusive_access (nav$switched_connections_list.access_control);
    osp$pop_inhibit_job_recovery;

  PROCEND nap$process_task_termination;
?? TITLE := 'NAP$REMOVE_NETWORK_WAITS', EJECT ??

  PROCEDURE [XDCL] nap$remove_network_waits
    (    activity_list: ost$i_wait_list);

{ The purpose of this request is to remove the current task from all network
{ wait queues.

    VAR
      index: integer,
      connection_id: nat$connection_id,
      executing_taskid: ost$global_task_id,
      file_instance: ^bat$task_file_entry,
      job_socket: ^nat$sk_job_socket,
      local_status: ost$status,
      previous_wait_for_connection: ^^nat$wait_for_connection,
      previous_wait_for_switch_offer: ^^nat$wait_for_switch_offer,
      server_attributes: ^nat$server_attributes,
      switched_connection: ^nat$switched_connection,
      wait_for_connection: ^nat$wait_for_connection,
      wait_for_switch_offer: ^nat$wait_for_switch_offer;

    pmp$get_executing_task_gtid (executing_taskid);
    index := 1;
    osp$push_inhibit_job_recovery;
    WHILE index <= UPPERBOUND (activity_list) DO
      CASE activity_list [index].activity OF
      = osc$i_null_activity, osc$i_await_time, pmc$i_await_task_termination =

      = pmc$i_await_local_queue_message =

      = nac$i_await_server_response =
        nap$remove_wait_server_response (activity_list [index].file^);
      = nac$i_await_connection =
        osp$begin_subsystem_activity;
        nlp$get_nonexclusive_access (nav$server_attributes_list.access_control);
        nap$find_server_attributes (activity_list [index].server, server_attributes);
        IF server_attributes <> NIL THEN
          nlp$get_exclusive_access (server_attributes^.access_control);
          wait_for_connection := server_attributes^.wait_for_connection;
          previous_wait_for_connection := ^server_attributes^.wait_for_connection;

          WHILE (wait_for_connection <> NIL) AND (wait_for_connection^.task_id <> executing_taskid) DO
            previous_wait_for_connection := ^wait_for_connection^.next_entry;
            wait_for_connection := wait_for_connection^.next_entry;
          WHILEND;

          IF wait_for_connection <> NIL THEN
            previous_wait_for_connection^ := wait_for_connection^.next_entry;
            FREE wait_for_connection IN nav$network_paged_heap^;
          IFEND;

          nlp$release_exclusive_access (server_attributes^.access_control);
        IFEND;
        nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);
        osp$end_subsystem_activity;

      = nac$i_await_switch_offer =
        nlp$get_exclusive_access (nav$switched_connections_list.access_control);

{ Check if the task had been waiting for switched connections.

        wait_for_switch_offer := nav$switched_connections_list.wait_for_switch_offer;
        previous_wait_for_switch_offer := ^nav$switched_connections_list.wait_for_switch_offer;
        WHILE (wait_for_switch_offer <> NIL) AND (wait_for_switch_offer^.destination_task_id <>
              executing_taskid) DO
          previous_wait_for_switch_offer := ^wait_for_switch_offer^.next_entry;
          wait_for_switch_offer := wait_for_switch_offer^.next_entry;
        WHILEND;

        IF wait_for_switch_offer <> NIL THEN
          previous_wait_for_switch_offer^ := wait_for_switch_offer^.next_entry;
          FREE wait_for_switch_offer IN nav$network_paged_heap^;
        IFEND;

        nlp$release_exclusive_access (nav$switched_connections_list.access_control);
      = nac$i_await_switch_accept =
        nap$get_connection_identifier (activity_list [index].file^, connection_id, local_status);
        IF local_status.normal THEN
          nlp$get_exclusive_access (nav$switched_connections_list.access_control);
          switched_connection := nav$switched_connections_list.switched_connection;
          WHILE (switched_connection <> NIL) AND (switched_connection^.connection_id <> connection_id) DO
            switched_connection := switched_connection^.next_entry;
          WHILEND;
          IF switched_connection <> NIL THEN
            IF switched_connection^.wait_for_switch_accept = executing_taskid THEN
              switched_connection^.wait_for_switch_accept.index := 0;
            IFEND;
          IFEND;
          nlp$release_exclusive_access (nav$switched_connections_list.access_control);
        IFEND;
      = nac$i_await_activity_status =

      = nac$i_await_data_available =
        file_instance := baf$task_file_entry_p (activity_list [index].file_identifier);
        IF file_instance <> NIL THEN
          IF file_instance^.device_class = rmc$network_device THEN
            nap$remove_wait_data_available (activity_list [index].file_identifier);
          ELSEIF file_instance^.device_class = rmc$terminal_device THEN
            IF file_instance^.st_open_file_dsc_pointer <> NIL THEN
              nap$remove_wait_data_available (file_instance^.st_open_file_dsc_pointer^.vtp_file_id);
            IFEND;
          IFEND;
        IFEND;
      = nac$i_await_title_translation, osc$i_await_unspecified_event =
        ;

      = nac$i_sk_await_clear_to_send =
        nlp$sk_lock_job_socket (activity_list [index].socket_identifier, job_socket);
        IF job_socket <> NIL THEN
          IF job_socket^.status = nac$sk_socket_open THEN
            IF job_socket^.socket_type = nac$sk_udp_socket THEN
              nlp$udp_remove_clear_to_send (job_socket^.global_socket_id);
            ELSEIF job_socket^.socket_type = nac$sk_tcp_socket THEN
              IF (job_socket^.tcp_socket_type = nlc$tcp_connect_socket) OR
                    (job_socket^.tcp_socket_type = nlc$tcp_accept_socket) THEN
                nlp$sk_tcp_remove_clear_to_send (job_socket^.connection_id);
              IFEND;
            IFEND;
          IFEND;
        IFEND;
        nlp$sk_unlock_job_socket (activity_list [index].socket_identifier);

      = nac$i_sk_await_data_available =
        nlp$sk_lock_job_socket (activity_list [index].socket_id, job_socket);
        IF job_socket <> NIL THEN
          IF job_socket^.status = nac$sk_socket_open THEN
            IF job_socket^.socket_type = nac$sk_udp_socket THEN
              nlp$udp_remove_data_available (job_socket^.global_socket_id);
            ELSEIF job_socket^.socket_type = nac$sk_tcp_socket THEN
              IF (job_socket^.tcp_socket_type = nlc$tcp_connect_socket) OR
                    (job_socket^.tcp_socket_type = nlc$tcp_accept_socket) THEN
                nlp$sk_tcp_remove_data_avail (job_socket^.connection_id);
              ELSEIF job_socket^.tcp_socket_type = nlc$tcp_listen_socket THEN
                nlp$sk_tcp_remove_accept_socket (job_socket^.application, job_socket^.port,
                      job_socket^.bound_address);
              IFEND;
            IFEND;
          IFEND;
        IFEND;
        nlp$sk_unlock_job_socket (activity_list [index].socket_id);

      = nac$i_sk_await_socket_offer =
        nlp$sk_remove_wait_socket_offer (activity_list [index].source_job);

      ELSE
      CASEND;

      index := index + 1;
    WHILEND;

    osp$pop_inhibit_job_recovery;

  PROCEND nap$remove_network_waits;
?? TITLE := 'NLP$ACCEPT_SWITCH_OFFER', EJECT ??

  PROCEDURE [XDCL, #GATE] nlp$accept_switch_offer
    (    file: fst$file_reference;
         source: jmt$system_supplied_name;
         attributes: ^nat$create_attributes;
         timesharing_connection_switch: boolean;
     VAR status: ost$status);

{ The purpose of this request is to acquire a connection that has been switched
{ by the SOURCE job to the currently executing job.


    VAR
      ignore_status: ost$status,
      destination_job_name: jmt$system_supplied_name,
      switched_connection: ^nat$switched_connection,
      user_supplied_name: jmt$user_supplied_name;

    status.normal := TRUE;

    IF (NOT jmv$executing_within_system_job) AND (NOT osp$is_caller_system_privileged ()) THEN
      osp$set_status_abnormal ('NA', nae$insufficient_privilege, 'nlp$accept_switch_offer', status);
      RETURN; {----->
    IFEND;


    pmp$get_job_names (user_supplied_name, destination_job_name, status);
    osp$push_inhibit_job_recovery;

    nlp$get_exclusive_access (nav$switched_connections_list.access_control);
    switched_connection := nav$switched_connections_list.switched_connection;

    WHILE (switched_connection <> NIL) AND ((switched_connection^.source_job_name <> source) OR
          (switched_connection^.destination_job_name <> destination_job_name) OR
          (switched_connection^.switch_status = nac$switch_complete)) DO
      switched_connection := switched_connection^.next_entry;
    WHILEND;

    IF switched_connection <> NIL THEN
      nap$create_network_file (file, attributes, switched_connection^.connection_id,
            timesharing_connection_switch, status);
      IF status.normal THEN
        update_application_connection (switched_connection^.application, switched_connection^.source_job_name,
              switched_connection^.connection_id);
        switched_connection^.switch_status := nac$switch_complete;
        { Ready the source task that had initiated the switch.
        IF switched_connection^.wait_for_switch_accept.index <> 0 THEN
          pmp$ready_task (switched_connection^.wait_for_switch_accept, ignore_status);
        IFEND;
      IFEND;
    ELSE
      osp$set_status_abnormal (nac$status_id, nae$no_switch_offered, destination_job_name, status);
    IFEND;

    nlp$release_exclusive_access (nav$switched_connections_list.access_control);
    osp$pop_inhibit_job_recovery;

  PROCEND nlp$accept_switch_offer;
?? TITLE := 'NLP$ACQUIRE_CONNECTION', EJECT ??

  PROCEDURE [XDCL, #GATE] nlp$acquire_connection
    (    server: nat$application_name;
         file: fst$file_reference;
         file_exists: boolean;
         attributes: ^nat$create_attributes;
     VAR status: ost$status);

{ The purpose of this procedure is to acquire a connection assigned to a given
{ server. The connection is either assigned to a particular job in which case it
{ can only be acquired by the job to which it has been assigned or it is assigned
{ to  any server job in which case it can be acquired by any server job. The
{ request is rejected if the server is inactive or has been deleted or if the
{ acquiring job has already acquired the max connections.

    VAR
      executing_job_name: jmt$system_supplied_name,
      ignore_status: ost$status,
      user_supplied_name: jmt$user_supplied_name;


    IF (NOT jmv$executing_within_system_job) AND (NOT osp$is_caller_system_privileged ()) THEN
      osp$set_status_abnormal ('NA', nae$insufficient_privilege, 'nlp$acquire_connection', status);
      RETURN; {----->
    IFEND;

    status.normal := TRUE;
    osp$push_inhibit_job_recovery;
    osp$begin_subsystem_activity;
    nlp$get_nonexclusive_access (nav$server_attributes_list.access_control);

    pmp$get_job_names (user_supplied_name, executing_job_name, ignore_status);
    acquire_connection (executing_job_name, server, file, file_exists, attributes, status);

    nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);
    osp$end_subsystem_activity;
    osp$pop_inhibit_job_recovery;

  PROCEND nlp$acquire_connection;
?? NEWTITLE := '[XDCL, #GATE] nlp$acquire_specific_connection', EJECT ??

{ PURPOSE:
{   The purpose of this request is the same as nap$acquire_connection except that
{   the job_name of the connection to acquire is passed as a parameter.

  PROCEDURE [XDCL, #GATE] nlp$acquire_specific_connection
    (    system_job_name: jmt$system_supplied_name;
         server: nat$application_name;
         file: fst$file_reference;
         file_exists: boolean;
         attributes: ^nat$create_attributes;
     VAR status: ost$status);

{ The purpose of this procedure is to acquire a connection assigned to a given
{ server and job.  The request is rejected if the server is inactive or has
{ been deleted or if the acquiring job has already acquired the max
{ connections.


    IF (NOT jmv$executing_within_system_job) AND (NOT osp$is_caller_system_privileged ()) THEN
      osp$set_status_abnormal ('NA', nae$insufficient_privilege, 'nlp$acquire_specific_connection', status);
      RETURN; {----->
    IFEND;

    status.normal := TRUE;
    osp$push_inhibit_job_recovery;
    osp$begin_subsystem_activity;
    nlp$get_nonexclusive_access (nav$server_attributes_list.access_control);

    acquire_connection (system_job_name, server, file, file_exists, attributes, status);

    nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);
    osp$end_subsystem_activity;
    osp$pop_inhibit_job_recovery;

  PROCEND nlp$acquire_specific_connection;
?? OLDTITLE ??
?? TITLE := 'NLP$CANCEL_SWITCH_OFFER', EJECT ??

  PROCEDURE [XDCL] nlp$cancel_switch_offer
    (    connection_id: nat$connection_id;
     VAR switch_complete: boolean;
     VAR status: ost$status);

    VAR
      previous_switched_connection: ^^nat$switched_connection,
      switched_connection: ^nat$switched_connection;

    status.normal := TRUE;
    osp$push_inhibit_job_recovery;
    nlp$get_exclusive_access (nav$switched_connections_list.access_control);
    switched_connection := nav$switched_connections_list.switched_connection;
    previous_switched_connection := ^nav$switched_connections_list.switched_connection;
    WHILE (switched_connection <> NIL) AND (switched_connection^.connection_id <> connection_id) DO
      previous_switched_connection := ^switched_connection^.next_entry;
      switched_connection := switched_connection^.next_entry;
    WHILEND;

    IF switched_connection = NIL THEN
      osp$set_status_abnormal (nac$status_id, nae$no_switch_offer_pending, 'on this file', status);
    ELSE
      switch_complete := switched_connection^.switch_status = nac$switch_complete;
      previous_switched_connection^ := switched_connection^.next_entry;
      FREE switched_connection IN nav$network_paged_heap^;
    IFEND;

    nlp$release_exclusive_access (nav$switched_connections_list.access_control);
    osp$pop_inhibit_job_recovery;

  PROCEND nlp$cancel_switch_offer;
?? TITLE := 'NLP$OFFER_CONNECTION_SWITCH', EJECT ??

  PROCEDURE [XDCL, #GATE] nlp$offer_connection_switch
    (    file: fst$file_reference;
         destination: jmt$system_supplied_name;
         timesharing_connection_switch: boolean;
     VAR status: ost$status);

{ The purpose of this procedure is to switch a connection from the currently
{ executing job to the destination job. The file associated with the connection
{ is marked. The switch request is rejected if the file has outstanding instances
{ of open.


    VAR
      application: nat$application_name,
      connection_id: nat$connection_id,
      ignore_status: ost$status,
      new_switched_connection: ^nat$switched_connection,
      previous_switched_connection: ^^nat$switched_connection,
      previous_wait_for_switch_offer: ^^nat$wait_for_switch_offer,
      source_job_name: jmt$system_supplied_name,
      switched_connection: ^nat$switched_connection,
      user_supplied_name: jmt$user_supplied_name,
      wait_for_switch_offer: ^nat$wait_for_switch_offer;

    IF (NOT jmv$executing_within_system_job) AND (NOT osp$is_caller_system_privileged ()) THEN
      osp$set_status_abnormal ('NA', nae$insufficient_privilege, 'nlp$offer_connection_switch', status);
      RETURN; {----->
    IFEND;

    status.normal := TRUE;
    nap$set_switch_offer (file, timesharing_connection_switch, connection_id, application, status);
    IF status.normal THEN
      osp$push_inhibit_job_recovery;
      nlp$get_exclusive_access (nav$switched_connections_list.access_control);
      REPEAT
        ALLOCATE new_switched_connection IN nav$network_paged_heap^;
        IF new_switched_connection = NIL THEN
          syp$cycle;
        IFEND;
      UNTIL new_switched_connection <> NIL;
      new_switched_connection^.destination_job_name := destination;
      pmp$get_job_names (user_supplied_name, source_job_name, status);
      new_switched_connection^.source_job_name := source_job_name;
      new_switched_connection^.application := application;
      new_switched_connection^.switch_status := nac$switch_pending;
      new_switched_connection^.wait_for_switch_accept.index := 0;
      new_switched_connection^.connection_id := connection_id;
      new_switched_connection^.next_entry := nav$switched_connections_list.switched_connection;
      nav$switched_connections_list.switched_connection := new_switched_connection;

{  Search wait_for_switch_offer queue for the waiting job, and if found
{  ready the waiting task.

      wait_for_switch_offer := nav$switched_connections_list.wait_for_switch_offer;
      previous_wait_for_switch_offer := ^nav$switched_connections_list.wait_for_switch_offer;

      WHILE (wait_for_switch_offer <> NIL) AND ((wait_for_switch_offer^.source_job_name <> source_job_name) OR
            (wait_for_switch_offer^.destination_job_name <> destination)) DO
        previous_wait_for_switch_offer := ^wait_for_switch_offer^.next_entry;
        wait_for_switch_offer := wait_for_switch_offer^.next_entry;
      WHILEND;

      IF wait_for_switch_offer <> NIL THEN
        previous_wait_for_switch_offer^ := wait_for_switch_offer^.next_entry;
        pmp$ready_task (wait_for_switch_offer^.destination_task_id, ignore_status);
        FREE wait_for_switch_offer IN nav$network_paged_heap^;
      IFEND;

      nlp$release_exclusive_access (nav$switched_connections_list.access_control);
      osp$pop_inhibit_job_recovery;

{ The intent of checking for the status condition nae$system_interrupt is to allow
{ the switch to act as though the switch has been started.

    ELSEIF (NOT status.normal) AND (status.condition = nae$system_interrupt) THEN
      status.normal := TRUE;
    IFEND;

  PROCEND nlp$offer_connection_switch;
?? TITLE := 'NLP$REQUEST_CONNECTION', EJECT ??

  PROCEDURE [XDCL, #GATE] nlp$request_connection
    (    server: nat$network_address;
         client: nat$application_name;
         file: fst$file_reference;
         protocol: nat$protocol;
         attributes: ^nat$create_attributes;
     VAR status: ost$status);

    VAR
      client_attributes: ^nat$client_attributes,
      connection_id: nat$connection_id,
      client_connection: ^nat$client_connection_attribute;

{ This procedure will execute in the user task.

    IF (NOT jmv$executing_within_system_job) AND (NOT osp$is_caller_system_privileged ()) THEN
      osp$set_status_abnormal ('NA', nae$insufficient_privilege, 'nlp$request_connection', status);
      RETURN; {----->
    IFEND;

    IF NOT nav$namve_active THEN
      osp$set_status_condition (nae$network_inactive, status);
      RETURN; {----->
    IFEND;

    status.normal := TRUE;
    osp$push_inhibit_job_recovery;
    osp$begin_subsystem_activity;
    nlp$get_nonexclusive_access (nav$client_attributes_list.access_control);
    nap$find_client_attributes (client, client_attributes);
    IF client_attributes = NIL THEN
      osp$set_status_abnormal (nac$status_id, nae$unknown_application, client, status);
    ELSE
      nlp$get_exclusive_access (client_attributes^.access_control);
      nap$validate_user (client_attributes^.client_capability, client_attributes^.client_ring,
            client_attributes^.client_system_privilege, status);
      IF NOT status.normal THEN
{ Client not authorized for this request.
        osp$set_status_abnormal (nac$status_id, nae$unknown_application, client, status);
      ELSE
        IF client_attributes^.client_status = nac$application_inactive THEN
          osp$set_status_abnormal (nac$status_id, nae$application_inactive, client, status);
        ELSE
          client_attributes^.attempted_connection_count := client_attributes^.attempted_connection_count + 1;
          IF client_attributes^.connection_count >= client_attributes^.max_connections THEN
            client_attributes^.rejected_connection_attempts :=
                  client_attributes^.rejected_connection_attempts + 1;
            osp$set_status_abnormal (nac$status_id, nae$application_max_conn_limit, client, status);
          ELSE
            IF (server.kind = nac$internet_address) OR (server.kind = nac$osi_transport_address) THEN
              IF client_attributes^.protocol = protocol THEN
                client_attributes^.connection_count := client_attributes^.connection_count + 1;
                nlp$release_exclusive_access (client_attributes^.access_control);
                nap$se_request_connection (client_attributes^.application_id, server, client, file,
                      attributes, client_attributes^.message_priority, connection_id, status);
                nlp$get_exclusive_access (client_attributes^.access_control);
                IF status.normal THEN
                  REPEAT
                    ALLOCATE client_connection IN nav$network_paged_heap^;
                    IF client_connection = NIL THEN
                      syp$cycle;
                    IFEND;
                  UNTIL client_connection <> NIL;
                  client_connection^.next_entry := client_attributes^.client_connections_list;
                  client_connection^.connection_id := connection_id;
                  client_attributes^.client_connections_list := client_connection;
                ELSE
                  client_attributes^.connection_count := client_attributes^.connection_count - 1;
                IFEND;
              ELSEIF (protocol = nac$cdna_session) OR (protocol = nac$cdna_virtual_terminal) THEN
                osp$set_status_abnormal (nac$status_id, nae$client_protocol_mismatch, 'CONNECTION', status);
              ELSE
                osp$set_status_condition (nae$unknown_protocol, status);
              IFEND;
            ELSEIF server.kind = nac$system_address THEN
              osp$set_status_condition (nae$address_protocol_mismatch, status);
            ELSE
              osp$set_status_condition (nae$unknown_address_kind, status);
            IFEND;
          IFEND;
        IFEND;
      IFEND;

      nlp$release_exclusive_access (client_attributes^.access_control);
    IFEND;

    nlp$release_nonexclusive_access (nav$client_attributes_list.access_control);
    osp$end_subsystem_activity;
    osp$pop_inhibit_job_recovery;

  PROCEND nlp$request_connection;
?? TITLE := 'ATTRIBUTE_SPECIFIED', EJECT ??

  FUNCTION [INLINE] attribute_specified
    (    attributes: ^nat$create_attributes;
         attribute: nat$connection_attribute_kind): boolean;

    VAR
      i: integer;

    IF attributes <> NIL THEN
      i := LOWERBOUND (attributes^);
      WHILE (i <= UPPERBOUND (attributes^)) AND (attributes^ [i].kind <> attribute) DO
        i := i + 1;
      WHILEND;
      attribute_specified := i <= UPPERBOUND (attributes^);
    ELSE
      attribute_specified := FALSE;
    IFEND;

  FUNCEND attribute_specified;
?? TITLE := 'UPDATE_APPLICATION_CONNECTION', EJECT ??

  PROCEDURE [INLINE] update_application_connection
    (    application: nat$application_name;
         source_job: jmt$system_supplied_name;
         connection_id: nat$connection_id);

{ The purpose of this procedure is to verify that the given application name is
{ known to application mgmt. If the connection belongs to a server application
{ job, it is retained as a server connection i.e it now belongs to the given
{ server application and not to a specific job.


    VAR
      server_job_attributes: ^nat$server_job_attributes,
      i: integer,
      ignore_status: ost$status,
      server_attributes: ^nat$server_attributes,
      server_connection: ^nat$server_connection_attribute;


    nlp$get_nonexclusive_access (nav$server_attributes_list.access_control);
    nap$find_server_attributes (application, server_attributes);
    IF server_attributes <> NIL THEN
      nlp$get_exclusive_access (server_attributes^.access_control);
      server_job_attributes := server_attributes^.server_job_list;
      WHILE (server_job_attributes <> NIL) AND (server_job_attributes^.job_name <> source_job) DO
        server_job_attributes := server_job_attributes^.next_entry;
      WHILEND;

      IF server_job_attributes <> NIL THEN
        server_connection := server_attributes^.server_connections_list;

      /search/
        WHILE server_connection <> NIL DO
          IF server_connection^.connection_id = connection_id THEN

{ Change the connection from a job to a server connection.
            IF (server_connection^.connection_kind = nac$owned_by_job) AND
                  (server_connection^.job_name = source_job) THEN
              server_connection^.connection_kind := nac$owned_by_server;
              server_job_attributes^.connection_count := server_job_attributes^.connection_count - 1;
            IFEND;
            EXIT /search/; {----->
          IFEND;
          server_connection := server_connection^.next_entry;
        WHILEND /search/;
      IFEND;

      nlp$release_exclusive_access (server_attributes^.access_control);
    IFEND;
    nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);

  PROCEND update_application_connection;
?? TITLE := 'ACQUIRE_CONNECTION', EJECT ??

  PROCEDURE acquire_connection
    (    system_job_name: jmt$system_supplied_name;
         server: nat$application_name;
         file: fst$file_reference;
         file_exists: boolean;
         attributes: ^nat$create_attributes;
     VAR status: ost$status);

    VAR
      acquire_in_progress: ^nat$server_connection_attribute,
      assigned_connection: ^nat$server_connection_attribute,
      connection_id: nat$connection_id,
      connection_released: boolean,
      i: integer,
      ignore_status: ost$status,
      previous_acquire_in_progress: ^^nat$server_connection_attribute,
      previous_assigned_connection: ^^nat$server_connection_attribute,
      server_attributes: ^nat$server_attributes,
      server_connection: ^nat$server_connection_attribute,
      server_job_attributes: ^nat$server_job_attributes;

    status.normal := TRUE;

    nap$find_server_attributes (server, server_attributes);
    IF server_attributes = NIL THEN { Unknown server.
      osp$set_status_abnormal (nac$status_id, nae$server_not_attached, server, status);
      RETURN; {----->
    IFEND;

    nlp$get_exclusive_access (server_attributes^.access_control);
    nap$validate_user (server_attributes^.server_capability, server_attributes^.server_ring,
          server_attributes^.server_system_privilege, status);
    IF NOT status.normal THEN

{ Server not authorized for this request.
      osp$set_status_abnormal (nac$status_id, nae$unknown_application, server, status);
    ELSEIF server_attributes^.server_status = nac$application_inactive THEN
      osp$set_status_abnormal (nac$status_id, nae$application_inactive, server, status);
    ELSE
      server_job_attributes := server_attributes^.server_job_list;
      WHILE (server_job_attributes <> NIL) AND (server_job_attributes^.job_name <> system_job_name) DO
        server_job_attributes := server_job_attributes^.next_entry;
      WHILEND;

      IF server_job_attributes = NIL THEN { Server not attached.
        osp$set_status_abnormal (nac$status_id, nae$server_not_attached, server, status);

      ELSEIF server_job_attributes^.connection_count >= server_job_attributes^.
            max_connections_per_server_job THEN

{          Job has already acquired max connections.

        osp$set_status_abnormal (nac$status_id, nae$max_connections_acquired, system_job_name, status);
      IFEND;
    IFEND;

    IF status.normal THEN
      previous_assigned_connection := ^server_attributes^.assigned_connections_list;
      assigned_connection := server_attributes^.assigned_connections_list;

      WHILE (assigned_connection <> NIL) AND (assigned_connection^.directed_connection) AND
            (assigned_connection^.destination_job_name <> system_job_name) DO
        previous_assigned_connection := ^assigned_connection^.next_entry;
        assigned_connection := assigned_connection^.next_entry;
      WHILEND;

      IF assigned_connection <> NIL THEN
        IF (server_attributes^.accept_connection) AND (attribute_specified (attributes, nac$connect_data))
              THEN

{ Connect_data attribute may not be specified if connection has already been accepted.

          osp$set_status_condition (nae$invalid_connect_data_change, status);
        ELSE

{ Move connection from the assigned connections queue to the acquire in progress queue.

          connection_id := assigned_connection^.connection_id;
          previous_assigned_connection^ := assigned_connection^.next_entry;
          assigned_connection^.next_entry := server_attributes^.acquire_in_progress;
          server_attributes^.acquire_in_progress := assigned_connection;

{ Update the connection count for the server job.

          server_job_attributes^.connection_count := server_job_attributes^.connection_count + 1;
          IF assigned_connection^.directed_connection THEN
            server_job_attributes^.assigned_connection_count :=
                  server_job_attributes^.assigned_connection_count - 1;
          IFEND;

          nlp$release_exclusive_access (server_attributes^.access_control);
          nap$create_network_file (file, attributes, connection_id, file_exists, status);

{ Since the global non exclusive lock to the server attributes list is not released, the server
{ cannot be deleted in the meantime.

          nlp$get_exclusive_access (server_attributes^.access_control);
          acquire_in_progress := server_attributes^.acquire_in_progress;
          previous_acquire_in_progress := ^server_attributes^.acquire_in_progress;
          WHILE (acquire_in_progress <> NIL) AND (acquire_in_progress^.connection_id <> connection_id) DO
            previous_acquire_in_progress := ^acquire_in_progress^.next_entry;
            acquire_in_progress := acquire_in_progress^.next_entry;
          WHILEND;

{ The resulting acquire_in_progress cannot be NIL. If it is NIL, it is a BUG.

          IF acquire_in_progress <> NIL THEN
            previous_acquire_in_progress^ := acquire_in_progress^.next_entry;
            IF NOT acquire_in_progress^.terminate_connection THEN
              IF status.normal THEN
                server_connection := acquire_in_progress;
                server_connection^.next_entry := server_attributes^.server_connections_list;
                server_connection^.connection_kind := nac$owned_by_job;
                server_connection^.job_name := system_job_name;
                server_attributes^.server_connections_list := server_connection;
              ELSE

{ Requeue the connection in the assigned connections list.

                acquire_in_progress^.next_entry := server_attributes^.assigned_connections_list;
                server_attributes^.assigned_connections_list := acquire_in_progress;

{ Update the connection count for the server job.

                server_job_attributes^.connection_count := server_job_attributes^.connection_count - 1;
                IF acquire_in_progress^.directed_connection THEN
                  server_job_attributes^.assigned_connection_count :=
                        server_job_attributes^.assigned_connection_count + 1;
                IFEND;
              IFEND;
            ELSE { Connection has been terminate by deactivate server request }

{ Update the connection count for the server.

              server_job_attributes^.connection_count := server_job_attributes^.connection_count - 1;
              server_attributes^.connection_count := server_attributes^.connection_count - 1;
              FREE acquire_in_progress IN nav$network_paged_heap^;
              IF status.normal THEN
                IF server_attributes^.server_status = nac$application_inactive THEN
                  osp$set_status_abnormal (nac$status_id, nae$application_inactive, server, status);
                ELSE

{ Server may have been deactivated and then activated again.

                  osp$set_status_abnormal (nac$status_id, nae$no_connection_available, server, status);
                IFEND;
                nlp$release_exclusive_access (server_attributes^.access_control);
                amp$return (file, ignore_status);
                RETURN; {----->
              ELSE { no file }
                nap$se_terminate_connection (connection_id, nac$application_deactivated, FALSE,
                      connection_released, ignore_status);
              IFEND;
            IFEND;
          ELSE

{ Should never end up here.

            nlp$release_exclusive_access (server_attributes^.access_control);
            nlp$release_nonexclusive_access (nav$server_attributes_list.access_control);
            osp$end_subsystem_activity;
            nap$namve_system_error (FALSE, 'Connection disappeared from the acquire in progress Q.', NIL);
          IFEND;
        IFEND;
      ELSE
        osp$set_status_abnormal (nac$status_id, nae$no_connection_available, server, status);
      IFEND;
    IFEND;

    nlp$release_exclusive_access (server_attributes^.access_control);

  PROCEND acquire_connection;
?? TITLE := 'DECREMENT_ASSIGNED_CONN_COUNT', EJECT ??

  PROCEDURE decrement_assigned_conn_count
    (    server_attributes: ^nat$server_attributes;
         job_name: jmt$system_supplied_name);

    VAR
      server_job_attributes: ^nat$server_job_attributes,
      local_status: ost$status;

    server_job_attributes := server_attributes^.server_job_list;
    WHILE (server_job_attributes <> NIL) AND (server_job_attributes^.job_name <> job_name) DO
      server_job_attributes := server_job_attributes^.next_entry;
    WHILEND;

    IF server_job_attributes = NIL THEN
{ This would happen if the job the connection was directed to terminated without acquiring a connection.
    ELSE
      server_job_attributes^.assigned_connection_count := server_job_attributes^.assigned_connection_count -
            1;
    IFEND;

  PROCEND decrement_assigned_conn_count;
*copyc nap$find_client_attributes
*copyc nap$find_server_attributes
*copyc nap$validate_user
*copyc nlp$get_exclusive_access
*copyc nlp$get_nonexclusive_access
*copyc nlp$release_exclusive_access
*copyc nlp$release_nonexclusive_access
MODEND nam$internal_connection_mgmt;
