?? RIGHT := 110 ??
?? TITLE := 'NOS/VE Permanent Files : Task Private Data Management' ??
MODULE pfm$task_private_data;

{ PURPOSE:
{   This module contains those permanent file manager routines that manage data
{   that is specific to a task.  All STATIC data contained in this module is
{   task specific.
{
{ DESIGN:
{   This module resides in the 23d library.
{
{   Task private data is used to:
{   1. improve performance;
{      Data that might be expensive to acquire and cannot change within the
{      execution of a task may be maintained.
{   2. provide a means for a task to run as if it were running on behalf of
{      another job.
{      The file server uses pfp$set_task_environment to set values within the
{      task.
{
{   There is no need to lock the data maintained in this module as it is task
{   specific; no other process may be accessing it.

?? NEWTITLE := '  Global Declarations Referenced by this module', EJECT ??
?? PUSH (LISTEXT := ON) ??
*copyc oss$task_private
*copyc ave$family_errors
*copyc ste$error_condition_codes
*copyc dft$client_job_list
*copyc pft$authority
*copyc pft$locked_catalog_list
*copyc pft$permit_level
*copyc pft$system_authority
*copyc pft$variant_path
?? POP ??
*copyc avp$family_administrator
*copyc avp$get_name_value
*copyc avp$system_administrator
*copyc pfp$report_unexpected_status
*copyc pmp$get_account_project
*copyc pmp$get_user_identification
*copyc stp$get_set_owner
*copyc avv$production_environ_begun
*copyc jmv$executing_within_system_job
*copyc osv$task_shared_heap
*copyc pfv$p_attached_pf_table
*copyc pfv$p_newest_queued_catalog
*copyc pfv$p_queued_catalog_table
*copyc pfv$queued_catalog_table_lock
?? TITLE := '  Global Declarations Declared by this module', EJECT ??

  VAR
    { osc$null_name inidcates an unknown value.
    pfv$family_administrator: [XDCL, STATIC, oss$task_private] boolean := FALSE,
    pfv$permit_level: [XDCL, oss$task_private, STATIC] pft$permit_level := pfc$pl_unknown,
    pfv$system_administrator: [XDCL, STATIC, oss$task_private] boolean := FALSE,
    pfv$system_authority: [XDCL, STATIC, oss$task_private] pft$system_authority := 0,
    pfv$task_account: [XDCL, STATIC, oss$task_private] avt$account_name := osc$null_name,
    pfv$task_family: [XDCL, STATIC, oss$task_private] ost$family_name := osc$null_name,
    pfv$task_project: [XDCL, STATIC, oss$task_private] avt$project_name := osc$null_name,
    pfv$task_user: [XDCL, STATIC, oss$task_private] ost$user_name := osc$null_name;

  VAR
    pfv$p_queued_catalog_table_lock: [XDCL, STATIC, oss$task_private] ^ost$signature_lock :=
          ^pfv$queued_catalog_table_lock,
    pfv$p_p_queued_catalog_table: [XDCL, STATIC, oss$task_private] ^pft$p_queued_catalog_table :=
          ^pfv$p_queued_catalog_table,
    pfv$p_p_newest_queued_catalog: [XDCL, STATIC, oss$task_private] ^pft$p_queued_catalog :=
          ^pfv$p_newest_queued_catalog,

    pfv$p_p_attached_pf_table: [XDCL, STATIC, oss$task_private] ^pft$p_attached_pf_table :=
          ^pfv$p_attached_pf_table,

    pfv$p_p_job_heap: [XDCL, STATIC, oss$task_private] ^^ost$heap := ^osv$task_shared_heap;

  VAR
    pfv$locked_apfid: [XDCL, STATIC, oss$task_private] 0 .. 0ffff(16) := 0;

  VAR
    pfv$locked_catalog_list: [XDCL, STATIC, oss$task_private] pft$locked_catalog_list :=
          [REP pfc$max_locked_catalogs of NIL];

  VAR
    administrator_status_known: [STATIC, oss$task_private] boolean := FALSE,
    set_name: [STATIC, oss$task_private] stt$set_name := '',
    set_owner: [STATIC, oss$task_private] ost$user_identification,
    set_owner_known: [STATIC, oss$task_private] boolean := FALSE;

?? TITLE := '  [XDCL, #GATE] pfp$get_authority', EJECT ??

  PROCEDURE [XDCL, #GATE] pfp$get_authority
    (    path: pft$complete_path;
         system_privilege: boolean;
     VAR authority: pft$authority;
     VAR status: ost$status);

{   The use of the static data assumes that the name of the family administrator
{ set owner, user id, or user's account_project will not change during execution
{ of the calling task.

    VAR
      same_family: boolean,
      same_master_catalog: boolean,
      user_id: ost$user_identification;

    authority.ownership := $pft$ownership [];
    IF (pfv$task_family = osc$null_name) OR (pfv$task_user = osc$null_name) THEN
      pmp$get_user_identification (user_id, status);
      IF status.normal THEN
        pfv$task_family := user_id.family;
        pfv$task_user := user_id.user;
      IFEND;
    ELSE
      status.normal := TRUE;
      user_id.family := pfv$task_family;
      user_id.user := pfv$task_user;
    IFEND;
    IF status.normal THEN
      authority.family := user_id.family;
      authority.user := user_id.user;
      same_family := (pfc$family_path_index <= UPPERBOUND (path)) AND
            (user_id.family = path [pfc$family_path_index]);
      same_master_catalog := (pfc$master_catalog_path_index <= UPPERBOUND (path)) AND
            (user_id.user = path [pfc$master_catalog_path_index]);
      IF same_family AND same_master_catalog THEN
        authority.ownership := authority.ownership + $pft$ownership [pfc$master_catalog_owner];
      IFEND;
      IF (pfv$task_account = osc$null_name) OR (pfv$task_project = osc$null_name) THEN
        pmp$get_account_project (authority.account, authority.project, status);
        IF status.normal THEN
          pfv$task_account := authority.account;
          pfv$task_project := authority.project;
        IFEND;
      ELSE
        authority.account := pfv$task_account;
        authority.project := pfv$task_project;
      IFEND;
    IFEND;

    IF status.normal THEN
      IF (NOT set_owner_known) OR (set_name <> path [pfc$set_path_index]) THEN
        stp$get_set_owner (path [pfc$set_path_index], set_owner, status);
        set_owner_known := status.normal;
        set_name := path [pfc$set_path_index];
      IFEND;
    IFEND;

    IF status.normal THEN
      IF set_owner = user_id THEN
        authority.ownership := authority.ownership + $pft$ownership [pfc$set_owner];
      IFEND;
      IF NOT administrator_status_known THEN
        IF jmv$executing_within_system_job AND NOT avv$production_environ_begun THEN
          { In system job, grant administrator status until production environment has been
          { established.
          pfv$system_administrator := TRUE;
          pfv$family_administrator := TRUE;
        ELSE
          pfv$system_administrator := avp$system_administrator ();
          pfv$family_administrator := avp$family_administrator ();
          administrator_status_known := TRUE;
        IFEND;
      IFEND;
    IFEND;

    IF status.normal THEN
      IF pfv$system_administrator THEN
        authority.ownership := authority.ownership + $pft$ownership [pfc$system_owner];
      ELSE
        IF pfv$family_administrator AND same_family THEN
          authority.ownership := authority.ownership + $pft$ownership [pfc$family_owner];
        IFEND;
        IF system_privilege THEN
          authority.ownership := authority.ownership + $pft$ownership [pfc$system_owner];
        IFEND;
      IFEND;
    ELSEIF (status.condition <> ste$set_not_active) AND (status.condition <> ste$not_allowing_access) THEN
      pfp$report_unexpected_status (status);
    IFEND;
  PROCEND pfp$get_authority;

?? TITLE := '  [XDCL, #GATE] pfp$get_ownership', EJECT ??
{ PURPOSE:
{   The purpose of this procedure is to determine the ownership of the task.
{
{ DESIGN:
{   An attempt will be made to determine set ownership only if a complete path
{   is provided.  If the family is served and this procedure is called from the
{   client mainframe, the ownership will not include set ownership.
{
{ Note:
{   The use of the static data assumes that the names of the system and family
{   administrators, the name of the set owner, and the user's identification
{   will not change during execution of the calling task.

  PROCEDURE [XDCL ,#GATE] pfp$get_ownership
    (    variant_path: pft$variant_path;
         system_privilege: boolean;
     VAR ownership: pft$ownership;
     VAR status: ost$status);

    VAR
      same_family: boolean,
      same_master_catalog: boolean,
      user_id: ost$user_identification;

    IF NOT administrator_status_known THEN
      IF jmv$executing_within_system_job AND NOT avv$production_environ_begun THEN
        {
        { Grant administrator status until production environment has been
        { established.
        {
        pfv$system_administrator := TRUE;
        pfv$family_administrator := TRUE;
      ELSE
        pfv$system_administrator := avp$system_administrator ();
        pfv$family_administrator := avp$family_administrator ();
        administrator_status_known := TRUE;
      IFEND;
    IFEND;

    IF pfv$system_administrator OR system_privilege THEN
      ownership := $pft$ownership [pfc$system_owner];
    ELSE
      ownership := $pft$ownership [];
    IFEND;

    IF (pfv$task_family = osc$null_name) OR (pfv$task_user = osc$null_name) THEN
      pmp$get_user_identification (user_id, status);
      IF status.normal THEN
        pfv$task_family := user_id.family;
        pfv$task_user := user_id.user;
      IFEND;
    IFEND;

    IF variant_path.complete_path THEN
      IF (NOT set_owner_known) AND (set_name <> variant_path.p_complete_path^ [pfc$set_path_index]) THEN
        stp$get_set_owner (variant_path.p_complete_path^ [pfc$set_path_index], set_owner, status);
        set_owner_known := status.normal;
        set_name := variant_path.p_complete_path^ [pfc$set_path_index];
      IFEND;

      IF set_owner = user_id THEN
        ownership := ownership + $pft$ownership [pfc$set_owner];
      IFEND;

      same_family := (pfc$family_path_index <= UPPERBOUND (variant_path.p_complete_path^)) AND
            (pfv$task_family = variant_path.p_complete_path^ [pfc$family_path_index]);
      same_master_catalog := (pfc$master_catalog_path_index <= UPPERBOUND (variant_path.p_complete_path^))
            AND (pfv$task_user = variant_path.p_complete_path^ [pfc$master_catalog_path_index]);
    ELSE
      same_family := (pfc$family_path_index <= UPPERBOUND (variant_path.p_path^)) AND
            (pfv$task_family = variant_path.p_path^ [pfc$family_name_index]);
      same_master_catalog := (pfc$master_catalog_path_index <= UPPERBOUND (variant_path.p_path^)) AND
            (pfv$task_user = variant_path.p_path^ [pfc$master_catalog_name_index]);
    IFEND;

    IF pfv$family_administrator AND same_family THEN
      ownership := ownership + $pft$ownership [pfc$family_owner];
    IFEND;

    IF same_family AND same_master_catalog THEN
      ownership := ownership + $pft$ownership [pfc$master_catalog_owner];
    IFEND;
  PROCEND pfp$get_ownership;

?? TITLE := '  [XDCL] pfp$get_permit_level', EJECT ??

  PROCEDURE [XDCL] pfp$get_permit_level
    (VAR permit_level: pft$permit_level;
     VAR status: ost$status);

    VAR
      number_of_names: avt$name_list_size,
      p_permit_level: ^avt$name_list;

    PUSH p_permit_level: [1 .. 1];
    avp$get_name_value (avc$permit_level, avc$user, p_permit_level^, number_of_names, status);
    IF status.normal THEN
      IF p_permit_level^ [1] = 'PUBLIC' THEN
        permit_level := pfc$pl_public;
        pfv$permit_level := pfc$pl_public;
        RETURN;
      ELSEIF p_permit_level^ [1] = 'FAMILY' THEN
        permit_level := pfc$pl_family;
        pfv$permit_level := pfc$pl_family;
      ELSEIF p_permit_level^ [1] = 'ACCOUNT' THEN
        permit_level := pfc$pl_account;
        pfv$permit_level := pfc$pl_account;
      ELSEIF p_permit_level^ [1] = 'PROJECT' THEN
        permit_level := pfc$pl_project;
        pfv$permit_level := pfc$pl_project;
      ELSEIF p_permit_level^ [1] = 'USER' THEN
        permit_level := pfc$pl_user;
        pfv$permit_level := pfc$pl_user;
      ELSEIF p_permit_level^ [1] = 'OWNER' THEN
        permit_level := pfc$pl_owner;
        pfv$permit_level := pfc$pl_owner;
      ELSE
        {
        { Treat as 'PUBLIC'.
        {
        permit_level := pfc$pl_public;
        pfv$permit_level := pfc$pl_public;
      IFEND;
    ELSE
      IF (status.condition = ave$unknown_field) OR
            (status.condition = ave$field_was_deleted) THEN
        {
        { Treat as 'PUBLIC'.
        {
        permit_level := pfc$pl_public;
        pfv$permit_level := pfc$pl_public;
        status.normal := TRUE;
      ELSEIF status.condition = ave$user_info_not_found THEN
        {
        { Temporarily treat as 'PUBLIC'.
        {
        permit_level := pfc$pl_public;
        status.normal := TRUE;
      ELSE
        pfp$report_unexpected_status (status);
      IFEND;
    IFEND;
  PROCEND pfp$get_permit_level;

?? TITLE := '  [XDCL] pfp$reset_administrator_status', EJECT ??

  PROCEDURE [XDCL] pfp$reset_administrator_status;

    pfv$system_administrator := avp$system_administrator ();
    pfv$family_administrator := avp$family_administrator ();
    administrator_status_known := TRUE;

  PROCEND pfp$reset_administrator_status;

?? TITLE := '  [XDCL] pfp$reset_task_environment', EJECT ??
{
{   This request resets a task's permanent file environment to its 'native'
{ environment.  The task will now run on behalf of the job of which it is a task
{ of, and the user that owns the job.  Any previously established environment
{ will be lost, and must have been cleaned up by the caller.
{

  PROCEDURE [XDCL] pfp$reset_task_environment;

    pfv$task_family := osc$null_name;
    pfv$task_user := osc$null_name;
    pfv$task_account := osc$null_name;
    pfv$task_project := osc$null_name;
    administrator_status_known := FALSE;
    set_owner_known := FALSE;
    set_name := osc$null_name;

    pfv$p_queued_catalog_table_lock := ^pfv$queued_catalog_table_lock;
    pfv$p_p_queued_catalog_table := ^pfv$p_queued_catalog_table;
    pfv$p_p_newest_queued_catalog := ^pfv$p_newest_queued_catalog;

    pfv$p_p_attached_pf_table := ^pfv$p_attached_pf_table;

    pfv$p_p_job_heap := ^osv$task_shared_heap;

  PROCEND pfp$reset_task_environment;

?? TITLE := '  [XDCL] pfp$set_family_administrator', EJECT ??

  PROCEDURE [XDCL] pfp$set_family_administrator
    (     family_administrator: boolean);

    IF family_administrator THEN
      pfv$family_administrator := TRUE;
        IF NOT administrator_status_known THEN
          pfv$system_administrator := avp$system_administrator ();
          administrator_status_known := TRUE;
        IFEND;
    ELSE
      administrator_status_known := FALSE;
    IFEND;

  PROCEND pfp$set_family_administrator;

?? TITLE := '  [XDCL] pfp$set_task_environment', EJECT ??
*copy pfh$set_task_environment

  PROCEDURE [XDCL] pfp$set_task_environment
    (    p_client_job_space: ^dft$client_job_space;
         system_administrator: boolean;
         family_administrator: boolean);

    pfv$task_family := p_client_job_space^.family;
    pfv$task_user := p_client_job_space^.user;
    pfv$task_account := p_client_job_space^.account;
    pfv$task_project := p_client_job_space^.project;
    administrator_status_known := TRUE;
    pfv$system_administrator := system_administrator;
    pfv$family_administrator := family_administrator;

    pfv$p_queued_catalog_table_lock := ^p_client_job_space^.queued_catalog_table_lock;
    pfv$p_p_queued_catalog_table := ^p_client_job_space^.p_queued_catalog_table;
    pfv$p_p_newest_queued_catalog := ^p_client_job_space^.p_newest_queued_catalog;

    pfv$p_p_attached_pf_table := ^p_client_job_space^.p_attached_pf_table;

    pfv$p_p_job_heap := ^p_client_job_space^.p_job_heap;
  PROCEND pfp$set_task_environment;

?? OLDTITLE, SKIP := 2 ??
MODEND pfm$task_private_data;
