#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); }