#include "updbldh.h"
#pragma title UPDBLD
#pragma eject
/*--------------------------------------------------------------------+
| |
| Copyright (c) 1996, SAS Institute Inc. |
| Unpublished - All Rights Reserved |
| |
| S A S / C S A M P L E |
| |
| Function : updbld |
| |
| Language: C |
| |
| Purpose : |
| This is the controlling function for creating the |
| IEBUPDTE input file. The list of members in the PDS |
| is provided by pdsgetm() in the form of two skiplist. |
| |
| The output DDN SYSPUNCH is verified to ensure the |
| attributes are LRECL=80 and RECFM=F, and BLKSIZE |
| is an even multiple of the LRECL. |
| |
| If there are alias members they are matched with their |
| corresponding real member based on TTR. Each real |
| member node has a pointer to a list of alias members |
| with matching TTR's. |
| |
| The alias list is terminated with a sentinel node to |
| mark the end of the list. |
| |
| Any alias members left over are orphans. Orphans are |
| added to the real member list and they will be treated |
| 'as if' they were real members. It will be noted on |
| IEBUPDTE ADD statement that it was a an orphan alias. |
| |
| The real member list is then sorted into alphabetic |
| order for final processing. |
| |
| Finally, we loop through the real member skiplist, |
| creating an ADD statement for each member, writing |
| data records for each member and writing out any |
| ALIAS statements that maybe needed for each member. |
| |
| Each ADD statement will indicate if the member is |
| a 'real' member or an 'alias' member being treated |
| as a real member. Additionaly, if a member, real |
| or alias, has no records it will be noted on the |
| ADD statement. |
| |
| Parameters: |
| NODE * (*memlist) - pointer to pointer of skiplist |
| with the real member names |
| |
| NODE * (*aliaslist)- pointer to pointer of skiplist |
| with the alias member names |
| |
| Returns : |
| EXIT_SUCCESS - IEBUPDTE input file has been |
| created |
| |
| EXIT_FAILURE - A failure/error has occured. A |
| unique message has been written to |
| stderr describing the condition. |
| |
| Notes : |
| - |
| |
| |
+--------------------------------------------------------------------*/
int updbld ( NODE * (*memlist), NODE * (*aliaslist) )
{
DCB_t * input = NULL;
DCB_t * output = NULL;
int exit_rc = EXIT_SUCCESS;
/*--------------------------------------------------------------------+
| Ensure no null pointers are passed and that there is at least one |
| node in the memlist skiplist. |
+--------------------------------------------------------------------*/
assert( (*memlist != NIL) && (aliaslist != NIL) );
printf("\n\n--------------------------------------------\n\n");
#pragma eject
/*--------------------------------------------------------------------+
| Setup and open input/output DCB's. Verify output DD DCB attributes |
| are correct and setup SYNAD exit for both input/output datasets. |
| The input DD DCB attributes have already been verified by the |
| caller. |
+--------------------------------------------------------------------*/
exit_rc = updverfi();
if (exit_rc == EXIT_SUCCESS)
{
exit_rc = updprep(&input, &output);
};
/*--------------------------------------------------------------------+
| Determine which alias entries have a real member, attach the alias |
| to the real member node. Alias members with no matching real |
| member will be added to the real member list and treated as if they |
| are real members. After this point, memlist has an entry for |
| all members that will be processed, aliaslist is no longer used. |
+--------------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS)
{
exit_rc = updaka(memlist, aliaslist);
};
#pragma eject
/*--------------------------------------------------------------------+
| Build a file formatted as input to IEBUPDTE. |
+--------------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS)
{
exit_rc = updproc(input, output, *memlist);
};
printf("\n\n--------------------------------------------\n\n");
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : updproc |
| |
| Language : C |
| |
| Purpose : updproc() positions the dataset to process each |
| member. It then calls updio() to create the IEBUPDTE |
| records for each member. |
| |
| updproc() detects that an alias is being treated as |
| real member and writes a message to stderr indicating |
| this anomaly has been detected. This is NOT an error. |
| |
| If updio() detects a member that has no records, empty |
| member, it signals this to updproc() via return code |
| and updproc() writes a message to stderr indicating |
| this anomaly has been detected at completion. This |
| is not a 'error' condition. |
| |
| After all members are processed the ENDUP statement |
| is written as the last record in the IEBUPDTE input |
| file and the total records in the output file is |
| written to stdout. |
| |
| Parameters: |
| DCB_t * input - DCB for input DDN SYSLIB |
| |
| DCB_t * output - DCB for output DDN SYSPUNCH |
| |
| NODE * memlist - Skiplist of members to process, |
| this list will contain: |
| 1) all real members found with |
| a list of its associated alias |
| members. |
| 2) Orhpaned alias members being |
| treated as if they are real |
| members. |
| |
| Returns : |
| EXIT_SUCCESS - Normal successful completion. |
| |
| ANOMALY - Normal successful completion but |
| there were orphaned alias members |
| and/or there were real members |
| that had no records, empty dataset.|
| |
| EXIT_FAILURE - A error/failure has occured. A |
| unique message will the written to |
| stderr describing the condition. |
| |
| Notes : |
| |
+--------------------------------------------------------------------*/
static int updproc ( DCB_t * input, DCB_t * output, NODE * memlist)
{
int exit_rc = EXIT_SUCCESS;
int osput_rc = EXIT_SUCCESS;
NODE * list; /* Pointer to next member to process */
NODE * walk; /* Pointer to member being processed */
int mem_records = 0;
int total_records = 0;
int orphan_alias = 0;
int empty_member = FALSE;
int alias_as_real = FALSE;
char endup_stmt[] = "./ ENDUP";
char out_rec[LRECL];
#pragma eject
/*------------------------------------------------------------------+
| Build IEBUPDTE input from the PDS members. Each member will get |
| ADD statement, then the data, then an ALIAS statement for each |
| existing alias(if any). All members searched for must be found. |
+------------------------------------------------------------------*/
list = memlist;
while ( exit_rc == EXIT_SUCCESS)
{
walk = list->pointers[0];
ospoint(input,walk->data.ttr_data.ttrz); /* look by ttrz */
if (walk->data.alias == TRUE)
{
alias_as_real = TRUE;
orphan_alias += 1;
};
exit_rc = updio(input, output, walk, &mem_records);
total_records += mem_records;
mem_records = 0;
list = walk;
/*-----------------------------------------------------------------+
| An empty member is ok, we just need to ensure the return code |
| gets set to indicate an anomaly has occured when we finish. |
+-----------------------------------------------------------------*/
if (exit_rc == ANOMALY)
{
exit_rc = EXIT_SUCCESS;
empty_member = TRUE;
};
/*-----------------------------------------------------------------+
| Terminate the loop if this was the last node or if the return |
| was not EXIT_SUCCESS. |
+-----------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS && list->pointers[0] == NIL)
{
exit_rc = LIST_END;
};
};
#pragma eject
/*--------------------------------------------------------------------+
| If all is well up to this point, close datasets and handle anomaly |
| conditions. |
+--------------------------------------------------------------------*/
if (exit_rc == LIST_END)
{
exit_rc = EXIT_SUCCESS;
/*----------------------------------------------------------------+
| There are two conditions which are called an ANOMALY. Each |
| condition is noted on the ADD statement, in the stdout listing |
| for that member and a note is placed in stderr indicating that |
| one or both conditions have been detected. |
| 1) Empty member, this can be a real member or an orpahned alias |
| member being treated as a real member |
| 2) Orphaned alias member. These are alias members which have |
| no corresponding real member which is based on ttr. Orphan |
| alias members are treated as real and may be empty. |
+----------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS)
{
if ( empty_member == TRUE)
{
fprintf(stderr,"\n\nThere are members which have no data"
" records (empty member)!\n");
fprintf(stderr,"Look for string '%s' in stdout.\n\n",
SOURCE_DS_EMPTY);
exit_rc = ANOMALY;
};
if ( alias_as_real == TRUE)
{
fprintf(stderr,"\n\nThere are orphaned alias entries "
"which were treated as real members!\n");
fprintf(stderr,"Look for string '%s' in stdout. \n\n",
ALIAS_REAL);
fprintf(stderr,
"\nNOTE: An orphaned alias member is an alias that\n");
fprintf(stderr,
" has no corresponding real member based on TTR.\n\n");
exit_rc = ANOMALY;
};
};
#pragma eject
/*-----------------------------------------------------------------+
| Write out ENDUP statment. |
+-----------------------------------------------------------------*/
memset(out_rec, ' ', LRECL);
memcpy(out_rec, endup_stmt, sizeof(endup_stmt)-1);
osput_rc = osput(output, out_rec, LRECL);
total_records += 1;
if (osput_rc != OSXXX_SUCCESS)
{
fprintf(stderr,"osput failed for %s\n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
};
osclose(input,"disp");
osclose(output,"disp");
printf("\nTotal Records in output: %8d\n", total_records);
};
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : updprep |
| |
| Language : C |
| |
| Purpose : Creates and opens the DCB's for input DDN SYSLIB |
| and output DDN SYSPUNCH. |
| |
| Parameters: |
| DCB_t * (*input) - DCB for input DDN SYSLIB |
| |
| DCB_t * (*output) - DCB for output DDN SYSPUNCH |
| |
| Returns : |
| EXIT_SUCCESS - normal successful completion |
| |
| EXIT_FAILURE - A error/failure has occured. A |
| unique message will be written to |
| stderr describing the condition. |
| |
| Notes : |
| |
+--------------------------------------------------------------------*/
static int updprep ( DCB_t * (*input), DCB_t * (*output))
{
int exit_rc = EXIT_SUCCESS;
DCB_t * prep_input;
DCB_t * prep_output;
int open_input_rc = 0;
int open_output_rc = 0;
exit_t inpt_exit_list[1] = {LAST | SYNAD, &synad_exit};
exit_t outp_exit_list[2] = {
{SYNAD, &synad_exit },
{LAST | ABEND, &abend_exit}
};
/*--------------------------------------------------------------------+
| Setup DCB for input DD and open the dataset. |
+--------------------------------------------------------------------*/
prep_input = osdcb(DDN_SYSLIB, "DSORG=PO", inpt_exit_list, 0);
if (prep_input == NULL)
{
fprintf(stderr,"osdcb failed for: %s \n", DDN_SYSLIB);
exit_rc = EXIT_FAILURE;
*input = NULL;
}
else
{
open_input_rc = osopen(prep_input, "input", 0);
if (open_input_rc == OSXXX_SUCCESS)
{
*input = prep_input;
}
else
{
fprintf(stderr,"osopen failed for: %s \n", DDN_SYSLIB);
exit_rc = EXIT_FAILURE;
*input = NULL;
};
};
#pragma eject
/*--------------------------------------------------------------------+
| Setup DCB for output DD and open the dataset. |
+--------------------------------------------------------------------*/
prep_output =
osdcb(DDN_SYSPUNCH, "LRECL=80,RECFM=F",outp_exit_list, 0);
if (prep_output == NULL)
{
fprintf(stderr,"osdcb failed for: %s \n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
*output = NULL;
}
else
{
open_output_rc = osopen(prep_output, "output",0);
if (open_output_rc == OSXXX_SUCCESS)
{
*output = prep_output;
}
else
{
fprintf(stderr,"osopen failed for: %s \n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
*input = NULL;
};
};
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : updverfi |
| |
| Language : C |
| |
| Purpose : Verify datasets exist for input DDN SYSLIB and output |
| DDN SYSPUNCH. Verify the dataset attributes for |
| the output DDN SYSPUNCH. Input DDN SYSLIB attributes |
| were verified when the PDS directory was processed. |
| |
| Parameters: |
| None |
| |
| Returns : |
| EXIT_SUCCESS - Normal successful completion |
| |
| EXIT_FAILURE - A error/failure occured. A unique |
| message will be written to stderr |
| describing the condition. |
| |
| Notes : |
| |
+--------------------------------------------------------------------*/
static int updverfi( void )
{
int exit_rc = EXIT_SUCCESS;
char recfm;
unsigned short dsorg;
int lrecl;
int blksize;
char dsname[44+1];
#pragma eject
/*------------------------------------------------------------------+
| Using osddinfo() and osdsinfo() determine attributes of the output|
| dataset. |
+------------------------------------------------------------------*/
/* use osddinfo() to get the dsname */
exit_rc = osddinfo(DDN_SYSPUNCH,dsname,NULL,NULL,NULL,NULL);
/*------------------------------------------------------------------+
| If there is no dsname returned from osddinfo() the DDN points |
| to something other than a dasd data set, i.e. SYSOUT, tape, etc. |
| |
| If this is the case then set exit_rc such that normal checking |
| will not be done, indicate to stdout what is going on, and |
| why. |
+------------------------------------------------------------------*/
if ( (strlen(dsname) < 1) && exit_rc == 0)
{
printf("\nFile being processed via output DD %s: "
"No Data Set Name Available! Data set is likely SYSOUT.",
DDN_SYSPUNCH);
printf("\n Note: normal checks for LRECL/DSORG/RECFM will be"
" suspended for this execution!\n\n\n");
exit_rc = NOT_A_DATASET;
}
else
{
if (exit_rc == 0)
{
/* Use osdsinfo() to get dsorg, lrecl, recfm, and blksize */
exit_rc = osdsinfo(dsname,0,&dsorg,&recfm,&lrecl,&blksize);
if (exit_rc != 0)
{
/* osdsinfo() failed, tell'm about it and exit */
fprintf(stderr,"\nOSDSINFO failed for output dataset!\n");
fprintf(stderr,"\nFilename via OSDDINFO: %s\n", dsname);
exit_rc = EXIT_FAILURE;
};
}
else
{
/* osddinfo() has failed, tell'm about it and exit */
fprintf(stderr,"\nOSDDINFO failed for output DD %s!\n",
DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
};
};
#pragma eject
/*------------------------------------------------------------------+
| Validate output dataset attributes. |
+------------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS) /* Continue if all is ok to this point*/
{
/*---------------------------------------------------------------+
| The file is present and we have all information necessary to |
| validate. Check for RECFM=F, LRECL=80, and a BLKSIZE that |
| is a multiple of LRECL. |
| |
| NOTE: RECFM_U must be specifically tested for first, as it is |
| RECFM_F or'ed with RECFM_V. |
+---------------------------------------------------------------*/
printf("\nFile being processed via output DD %s: %s\n\n",
DDN_SYSPUNCH, dsname);
if ( (recfm & RECFM_U ) == RECFM_U )
{
fprintf(stderr,
"\nFile being processed via output DD %s: %s\n\n",
DDN_SYSPUNCH, dsname);
exit_rc = EXIT_FAILURE;
fprintf(stderr,"File ->was<- RECFM=U, only FIXED allowed!\n");
};
if ( lrecl != LRECL)
{
fprintf(stderr,
"\nFile being processed via output DD %s: %s\n\n",
DDN_SYSPUNCH, dsname);
fprintf(stderr,"File LRECL was not 80!\n");
exit_rc = EXIT_FAILURE;
if ( (blksize%lrecl) != 0)
{
fprintf(stderr,
"\nFile being processed via output DD %s: %s\n\n",
DDN_SYSPUNCH, dsname);
exit_rc = EXIT_FAILURE;
fprintf(stderr,"File BLKSIZE is not a multiple of LRECL)!\n");
};
};
if ( (recfm & RECFM_F) != RECFM_F )
{
fprintf(stderr,
"\nFile being processed via output DD %s: %s\n\n",
DDN_SYSPUNCH, dsname);
fprintf(stderr,"File was not RECFM=F!\n");
exit_rc = EXIT_FAILURE;
};
};
/*------------------------------------------------------------------+
| If the only thing detected was the fact that this is not a dasd |
| dataset, then set return to EXIT_SUCCESS. |
+------------------------------------------------------------------*/
if (exit_rc == NOT_A_DATASET)
{
exit_rc = EXIT_SUCCESS;
};
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : updio |
| |
| Language : C |
| |
| Purpose : This function creates the ADD statement, writes out |
| the data records for the member(if any exist), and |
| creates ALIAS statements if there are alias members. |
| |
| updio() determines the source for the member, it will |
| be either 'REAL MEMBER' or 'ALIAS AS REAL', and notes |
| it on the ADD statement as well as the entry written |
| to stdout for this member. |
| |
| In creating the ADD statement updio() determines if |
| the member is empty (no data records). It the member |
| is empty, it is noted on the ADD statement and in the |
| entry in stdout for this member. |
| |
| A member that is empty (no records) is considered |
| an anomaly, not an error. This condition is signaled |
| to the caller with a return code of ANOMALY. |
| |
| Parameters: |
| DCB_t * input - opened input dataset DDN SYSLIB |
| |
| DCB_t * output - opened output dataset DDN SYSPUNCH |
| |
| NODE * real_member - node address of the member to |
| be processed |
| |
| int * mem_records - total records written for this |
| member, inlcudes ADD and any ALIAS |
| statements needed, plus data |
| records, if any |
| |
| Returns : |
| EXIT_SUCCESS - Normal successful completion. |
| |
| ANOMALY - Normal successful completion that |
| indicates that the member being |
| processed is empty. |
| |
| EXIT_FAILURE - A error/failure has occured. A |
| unique message will be written to |
| stderr describing the condition. |
| |
| Notes : |
| - IEBUPDTE will not accept empty members, although |
| empty member are valid. |
| |
| |
+--------------------------------------------------------------------*/
static int updio ( DCB_t * input, DCB_t * output, NODE * real_member,
int * mem_records)
{
void * rec_data = NULL;
int rec_len;
int exit_rc = OSXXX_SUCCESS;
int member_empty = FALSE;
ALIAS_DATA * listalias;
ALIAS_DATA * freealias;
char add_stmt[] = "./ ADD NAME=";
char alias_stmt[] = "./ ALIAS NAME=";
char out_rec[LRECL];
#pragma eject
/*------------------------------------------------------------------+
| Start building the ADD statement, it will be completed after |
| we determine if there are records in the member. |
+------------------------------------------------------------------*/
memset(out_rec, ' ', LRECL);
memcpy(out_rec, add_stmt, sizeof(add_stmt)-1);
memcpy(&out_rec[sizeof(add_stmt)-1],
real_member->data.member, 8);
printf("Member: %.8s ", real_member->data.member);
/*------------------------------------------------------------------+
| Mark member as real or alias as real, note it in stdout and on |
| the ADD statement. |
+------------------------------------------------------------------*/
if (real_member->data.alias == TRUE)
{
printf("%s", ALIAS_REAL);
memcpy(&out_rec[ (sizeof(add_stmt)-1) + 8 + 2],
ALIAS_REAL, sizeof(ALIAS_REAL) - 1 );
}
else
{
printf("%s", REAL_MEMBER);
memcpy(&out_rec[(sizeof(REAL_MEMBER)-1) + 8 + 2],
REAL_MEMBER, sizeof(REAL_MEMBER) - 1 );
};
#pragma eject
/*------------------------------------------------------------------+
| Complete the ADD statement by determining if the member has |
| records or if it is empty. |
| |
| 1) If the member has records: |
| - write out the ADD statment as is, stdout will be completed |
| later when the number of records in the member has been |
| determined. |
| |
| 2) If the member is empty: |
| - turn on empty member switch, indicates an anomaly condition |
| - indicate in ADD statment that it is an empty member |
| - ditto for stdout |
| - write out the ADD statment |
| |
+------------------------------------------------------------------*/
exit_rc = osget(input, &rec_data, &rec_len);
*mem_records = 0;
switch(exit_rc)
{
case OSGET_EOF: /* Handle emtpy member */
member_empty = TRUE;
memcpy(&out_rec[48],SOURCE_DS_EMPTY,
sizeof(SOURCE_DS_EMPTY)-1);
printf(" Records: %s\n", SOURCE_DS_EMPTY);
exit_rc = osput(output, out_rec, LRECL); /* ADD statement */
if (exit_rc == OSXXX_SUCCESS)
{
exit_rc = OSGET_EOF; /* fall thru records processing */
}
else
{
fprintf(stderr,"osput failed for %s\n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
};
break;
case OSXXX_SUCCESS: /* Handle member with records */
exit_rc = osput(output, out_rec, LRECL); /* ADD statement */
if (exit_rc != OSXXX_SUCCESS)
{
fprintf(stderr,"osput failed for %s\n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
};
break;
default:
fprintf(stderr,"osget failed for %s\n", DDN_SYSLIB);
exit_rc = EXIT_FAILURE;
};
#pragma eject
/*------------------------------------------------------------------+
| If the member has records, process them by reading and writing |
| each record, 'as is'. Note, the first record will already be |
| in the buffer at entry to the while_loop. |
+------------------------------------------------------------------*/
while(exit_rc == OSXXX_SUCCESS)
{
exit_rc = osput(output, rec_data, rec_len);
*mem_records += 1; /* Member records ONLY */
if (exit_rc == OSXXX_SUCCESS)
{
exit_rc = osget(input, &rec_data, &rec_len);
if ( (exit_rc != OSXXX_SUCCESS) && (exit_rc != OSGET_EOF) )
{
fprintf(stderr,"osget failed for %s\n", DDN_SYSLIB);
exit_rc = EXIT_FAILURE;
};
}
else
{
fprintf(stderr,"osput failed for %s\n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
};
};
#pragma eject
/*------------------------------------------------------------------+
| Display number of records for this member which completes the |
| stdout 'member name' line. If there are alias entries, write out |
| an ALIAS statment for them and display their names in stdout. |
+------------------------------------------------------------------*/
if ( exit_rc == OSGET_EOF )
{
if ( *mem_records > 0 )
printf(" Records: %8d\n", *mem_records);
*mem_records += 1; /* account for ADD statment in total records */
/*---------------------------------------------------------------+
| Write an ALIAS statement for each alias member that exist for |
| this member. Free each alias node as we write it. |
+---------------------------------------------------------------*/
if (real_member->data.alias_list != NULL)
{
printf(" Alias entries for this member: \n");
/* Setup alias processing loop and build the alias statement */
listalias = real_member->data.alias_list;
exit_rc = OSXXX_SUCCESS;
memset(out_rec,' ',LRECL);
memcpy(out_rec, alias_stmt, sizeof(alias_stmt)-1);
while( ( listalias->next_alias) != NULL
&& exit_rc == OSXXX_SUCCESS)
{
memcpy(&out_rec[14], listalias->member, 8);
exit_rc = osput(output, out_rec, LRECL);
if (exit_rc != OSXXX_SUCCESS)
{
fprintf(stderr,"osput failed for %s\n", DDN_SYSPUNCH);
exit_rc = EXIT_FAILURE;
};
*mem_records += 1; /* account for ALIAS statment in total */
printf(" AliasName: %s\n", listalias->member);
freealias = listalias;
listalias=listalias->next_alias;
free(freealias);
};
if (exit_rc == OSXXX_SUCCESS)
{
exit_rc = EXIT_SUCCESS;
};
/* The last member of the alias list is a sentinel node */
/* which allowed the last real member of the list to be */
/* processed. We must now free the sentinel member also. */
free(listalias); /* free the sentinel node */
}
else
{
/* No alias members to process and all else went ok */
exit_rc = EXIT_SUCCESS;
};
};
/*-------------------------------------------------------------------+
| If exit_rc is EXIT_SUCCESS, there have been no errors/failures to |
| this point. We then determine if there ANOMALY conditons we need |
| inform the caller about. |
+-------------------------------------------------------------------*/
if (member_empty == TRUE && exit_rc == EXIT_SUCCESS)
{
exit_rc = ANOMALY; /* Anomaly conditions exist, say so! */
};
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : updaka |
| |
| Language : C |
| |
| Purpose : Locate and attach alias entries to their corresponding |
| real member. When a match is found based on TTR, |
| the alias member name is added to the list of alias |
| names for the real member, the list is pointed too by |
| the node. |
| |
| Any alias member left over are considered orphaned and |
| are added to the real member list as a 'normal' member. |
| From this point on, they will be treated as 'real' |
| members. |
| |
| The memlist is resorted in alphabetical order for |
| final processing. |
| |
| |
| Parameters: |
| NODE * (*memlist) - pointer to pointer of skiplist |
| with the real member names |
| |
| NODE * (*aliaslist)- pointer to pointer of skiplist |
| with the alias member names |
| |
| Returns : EXIT_SUCCESS - alias members have been processed. |
| EXIT_FAILURE - insert_alias() ran out of memory. |
| |
| Notes : |
| |
+--------------------------------------------------------------------*/
static int updaka ( NODE * (*memlist), NODE * (*aliaslist) )
{
int exit_rc = EXIT_SUCCESS;
int compare_rc = EXIT_SUCCESS;
NODE * list_by_name = NULL;
NODE * new_node = NULL;
NODE * list = NULL;
NODE * temp = NULL;
NODE * match_node = NULL;
/*------------------------------------------------------------------+
| If a real member exist for this alias (based on TTR) insert the |
| alais name in the list provided for in each real member node. |
+------------------------------------------------------------------*/
list = *aliaslist;
while( ((temp = list->pointers[0]) != NIL) && exit_rc == EXIT_SUCCESS)
{
match_node = search_node(compare_by_ttr, *memlist, &temp->data);
if (match_node != NIL)
{
exit_rc = insert_alias(match_node, &temp->data);
};
list = temp;
};
/*------------------------------------------------------------------+
| Reorder real member list by member name. |
+------------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS)
{
list = *memlist; /* walking node pointer */
list_by_name = newlist(); /* Initial new for member order */
while( (temp = list->pointers[0]) != NIL)
{
new_node = insert_node(compare_by_name,
list_by_name, &temp->data);
list = temp; /* Next list member please */
};
freelist(*memlist); /* Free original real member skiplist */
*memlist = list_by_name; /* Replace it with the new skiplist */
};
/*------------------------------------------------------------------+
| Alias members left in the aliaslist (member names are other than |
| REALMEMB) will be added to the real member skiplist, they will be |
| processed as 'real' members, with a comment indicating they |
| are really 'alias' members which were orphaned. |
+------------------------------------------------------------------*/
if (exit_rc == EXIT_SUCCESS)
{
list = *aliaslist;
while( (temp = list->pointers[0]) != NIL )
{
compare_rc = memcmp(temp->data.member,REALMEMB, 8);
if (compare_rc != EQUAL )
{
new_node = insert_node(compare_by_name,
list_by_name, &temp->data);
};
list = temp;
};
};
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : insert_alias |
| |
| Language : C |
| |
| Purpose : Insert an alias member in the list for its matching |
| real member. If no alias list exist, one is |
| initialized and then the alias member name node is |
| added to the list. |
| |
| Alias members are added to a list anchored by a pointer |
| in the match_node structure. The list is terminated |
| by a sentinel node which is null. The purpose of the |
| sentinel node is to provide a simple way for other |
| functions using the list to find the end. Alias |
| members are added to the list between the last node |
| and the sentinel node, this keeps the list in the |
| order in which the alias members were added. |
| |
| Parameters: |
| NODE * match_node - matching node for the alias |
| |
| PDS_MBR * alias_mem - alias member information |
| |
| Returns : EXIT_SUCCESS - alias was added to the list |
| EXIT_FAILURE - ran out of memory |
| |
| Notes : |
| |
| |
+--------------------------------------------------------------------*/
static int insert_alias ( NODE * match_node, PDS_MBR * alias_mem )
{
int exit_rc = EXIT_SUCCESS;
ALIAS_DATA * new_alias;
/*------------------------------------------------------------------+
| Build an alias node and insert it into the list of alias members |
| for this matching real member. |
+------------------------------------------------------------------*/
new_alias = calloc(1,sizeof(ALIAS_DATA));
if (new_alias == NULL)
{
fprintf(stderr,"\nNULL pointer returned from calloc().\n\n");
fprintf(stderr,"\n At line %d in %s\n", __LINE__,__FILE__);
exit_rc = EXIT_FAILURE;
}
else
{
memcpy(new_alias->member, alias_mem->member, 8);
if (match_node->data.alias_list == NULL)
{
/* Alloacate a sentinel node to mark the end of the list */
/* and chain it behind the newly created alias node */
new_alias->next_alias = calloc(1,sizeof(ALIAS_DATA));
if (new_alias->next_alias == NULL)
{
fprintf(stderr,"\nNULL pointer returned from calloc().\n\n");
fprintf(stderr,"\n At line %d in %s\n", __LINE__,__FILE__);
exit_rc = EXIT_FAILURE;
}
else
{
/* Initialize the alias_list and alias_last to new node */
match_node->data.alias_list = new_alias;
match_node->data.alias_last = new_alias;
};
}
else
{
/* Chain new alias to sentinel node. */
new_alias->next_alias = match_node->data.alias_last->next_alias;
/* Chain last alias to new alias */
match_node->data.alias_last->next_alias = new_alias;
/* Make new alias the last alias in the list */
match_node->data.alias_last = new_alias;
};
/*---------------------------------------------------------------+
| Mark this alias as having a matching real member. |
+---------------------------------------------------------------*/
memcpy(alias_mem->member, REALMEMB, 8);
};
return(exit_rc);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : abend_exit |
| |
| Purpose : Handle abends on output dataset for x37 only. |
| |
| Parameters: |
| void * abend_info_ptr - abend code and action |
| |
| Returns : 0 - always |
| |
| Notes : |
| |
+--------------------------------------------------------------------*/
static int abend_exit ( void * abend_info_ptr, void * not_used)
{
struct ABEND_INFO * abend_info;
abend_info = (struct ABEND_INFO *) abend_info_ptr;
if ( (abend_info->abend_code == 0xb37 ||
abend_info->abend_code == 0xd37 ||
abend_info->abend_code == 0xe37 ) &&
abend_info->ok_to.ignore
)
{
/* Ignore full condition and allow code to handle */
abend_info->action = 4;
fprintf(stderr,"Output dataset is full for %s\n", DDN_SYSPUNCH);
}
else
{
/* Do not continue, abend now. This can not be ingnored. */
abend_info->action = 4;
};
return(0);
}
#pragma eject
/*--------------------------------------------------------------------+
| |
| Function : synad_exit |
| |
| Language : C |
| |
| Purpose : Handle I/O error condtions for SYSLIB and SYSPUNCH. |
| This allows for the full error message to be displayed. |
| |
| Parameters: |
| void * synadf_info_ptr - address of message constructed by |
| SYNADF |
| void * decb_ptr - DECB for the DD causing the SYNAD exit |
| to be called |
| |
| Returns : 0 - always |
| |
| Notes : |
| |
| |
+--------------------------------------------------------------------*/
static int synad_exit ( void * synadf_info_ptr, void * decb_ptr)
{
struct SYNAD_INFO * synad_info;
DECB_t * decb;
/* cast pointers to correct data types for processing */
synad_info = (struct SYNAD_INFO *) synadf_info_ptr;
decb = (DECB_t *) decb_ptr;
/*------------------------------------------------------------------+
| Check for PDSE and handle the additional message data that is |
| provided for them. |
+------------------------------------------------------------------*/
if (synad_info->msg1[113] == 'S') /* 'S' is a PDSE. */
{
fprintf(stderr,"I/O Error while processing a DSORG=PDSE "
"data set, SYNAD message text follows - \n");
fprintf(stderr,"\n Message : %.114s\n", synad_info->msg1);
fprintf(stderr,"\n PDSE-Info: %.40s\n\n", synad_info->msg2);
}
else
{
fprintf(stderr,"I/O Error while processing a DSORG=PO data set, "
" SYNAD message text follows - \n");
fprintf(stderr,"\n Message : %.114s\n\n", synad_info->msg1);
};
return(0);
}
|