/****************************************************************************
* This performance improve code for SoftLoad 3.0 are focus on
*  a. Reduced repeat sorting on bundles.<platform> and
*     pkginfo.<platform>.
*  b. Reduced .ok and .nok file open(s)/close(s) in pdt and
*     pkg directories.
*  c. Reduced time on "Loading current installation history".
*  d. Reduced time on "Loading appropriate product installation information."
*  e. Reduced time on "Retrieving product status"
* ----------------------------------------------------------------------------
* Six script files and one .c file are modified to improve performance of
* the SoftLoad v3.0.
* They are bundle_fltr.pp, choice_fltr.pp, load_fltr.pp, softload.pp,
*      softload_GUI.pp, vld.pp and process_file.c
* ---------------------------------------------------------------------------
* Usage:
*    process_file 1 p <Proot> i <inputFile> 
*    process_file 2 p <Proot> i <inputFile> [ k [pkgs/pdts] [ok/nok] ]
*    process_file 3 p <Proot> i <inputFile> (S)
*    process_file 4 p <Proot> i <inputFile> [ F|f] <bit> ]
*    process_file 5 p <Proot> i <inputFile> (S)

*  case number 1:  
*  --------------
*     Replace code:
*       1. sort -u +2 -3 $bundles | $BOURNE check_load && cantInstall="true"
*            (softload.pp)
*       2. sort -u +2 -3 $bundles | $BOURNE check_load && LOAD_OPT="$UNAVAILABLE"
*            (softload.pp)
*       3. sort -u +2 -3 $bundles | $BOURNE check_load && loadOpt="noLoad" 
*            (softload_GUI.pp) 
*     It is to find .ok files in install/pdts directory.
*     return status :
*       0   normal exit
*       1   usage error
*       11  find all .ok file in install/pdts directory
*
*  case number 2:
*  -------------- 
*     Replace code:
*      1. ./overwrite /tmp/pdt$$ $BOURNE status_fltr -pkg -v ok < /tmp/pdt$$
*                   (bundle_fltr.pp)
*      2. sort -u +2 -3 $infile | $BOURNE status_fltr nok > $outfile
*                   (load_fltr.pp)
*      3. ./overwrite $outfile $BOURNE status_fltr -v ok < $outfile
*                   (load_fltr.pp)
*     It is to find either .ok or .nok in install/pdts or install/pkgs
*       directory.
*     return status:
*       0   normal exit
*       1   usage error
*     output is in  
*       stdout 
*   
*  case number 3:
*  -------------- 
*        replace code:
*          sort -u +2 -3 $infile | $BOURNE inv_pdts -S > $tmpfl2 (bundle_fltr.pp) 
*  case number 5:
*  -------------- 
*        replace code:
*          1.  $BOURNE pkg_fltr $bundles -ok -nok $pkgstrs | $BOURNE inv_pdts | $jsr Page
*             (vld.pp)
*          2. $BOURNE pkg_fltr $bundles -ok -nok | $BOURNE inv_pdts -S > $tmpfl1
*             (vld.pp) 
* 
*       Both cases read product lines from stdin and display an inventory of
*       products installed, failed, and availble.  Case 5 will filter out the
*       empty line and "==>" in the first line of .ok and .nok file in pdts/pkgs
*       directory.
*
*       option S: Don't print out the header
*
*  case number 4: Combine 2 pipes to one open/close. 
*  --------------
*        replace code:
*        1.   awk '{ '"$field"' }' $infile | tr '~' ' ' | {
*              $columnize -n $gutterWidth $columns 
*              | $jsr Page
*                (choice_fltr.pp) 
*        2.   awk '{print $1}' $outfile | tr '~' ' ' |
*              $columnize $gutterWidth $columns | $jsr Page
*                 | $columnize $gutterWidth $columns in choice_fltr
*                (choice_fltr.pp)
*/


/*
 * include system header
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>

/*
 * macro define
 */
#ifndef TRUE
#define TRUE     1
#define FALSE    0
#endif    

#ifndef MAXPATHLEN
#   define MAXPATHLEN 1024
#endif

#define PROD     0 
#define PKG      1	
     
#define PROGNAME "process_file.c: "
#define LENGTH   255
#define WORDLEN  55 

/*
 * global variables
 */
char *usage;

FILE   	*ifd;                   /* input file descriptor   */
int    	caseNum;		/* case number             */
char   	*iFileNam;  /* input file name         */
char   	*prodName;       /* pdts or pkgs level      */
char  	*suffix;           /* suffix file .ok or .nok */
char     *Proot;
char     *vendor;
/*NewLine*/
char    *iFileNam2; 		/*second input file name   */
char 	*Vendor;		/*The name of the vendor*/


/*
 * extern function declaration
 */ 
extern  int fclose();

/*
 * functions
 */

/*
 * exitHdr: exit with a number and 
 *          do exit handler
 */
void 
exitHdr (exitCode)
int exitCode;
{
    if (ifd)
       (void)fclose(ifd);

    exit(exitCode);
}

/*
 * case 1 
 *   checkLoad():
 *   This function checks product lines from bundles file to stdout that
 *   correspond to products that have a file ending in ok in install/pdts
 *   directory.  If all product lines have correspond products.ok file then
 *   return 11.                         
 */
int 
checkLoad()
{
    char   line[LENGTH+1];
    char   desc[LENGTH+1], pkgname[LENGTH+1], pdtname[LENGTH+1];
    char   fileline[2*MAXPATHLEN+1];
    char   pdtsize[LENGTH+1];
    char   platform[20];
    char   FMrelease[20];
    struct stat stbuf;

    while ( fgets(line, LENGTH, ifd ))  /* read a line */
    {
         if ( sscanf( line,"%s%s%s%s%s%s",desc,pkgname,pdtname,
                    pdtsize, platform, FMrelease) == 6)  
         {
            (void)sprintf(fileline,"%s/install/pdts/%s_%s_%s.ok",
                         Proot,pdtname,platform,FMrelease);
            if (!stat(fileline, &stbuf))   /* find ok file */ 
            ;
            else
               exitHdr(0);  /* exit if can not find ok file */ 
         }
         else
         {
            (void)fprintf(stdout,"%sFormat Error of <%s>\n",PROGNAME,iFileNam);
             exitHdr(1);
         }
    }
    exitHdr(11);
}

/* case 2
 * statusFltr():
 * if check .ok file doesnot exsit in {pdts|pkgs], then print out the line
 *    in input file to output file. (status_fltr -v ok)
 * if check .nok file exists in {pdts|pkgs], then print out the line
 *    in input file to output file.  (status_fltr nok)
 */
int
statusFltr()
{
    char   line[LENGTH+1];
    char   desc[LENGTH+1], pkgname[LENGTH+1], pdtname[LENGTH+1];
    char   fileline[2*MAXPATHLEN+1];
    char   fileline1[2*MAXPATHLEN+1];
    char   pdtsize[LENGTH+1];
    char   platform[20], CDnum[20], FSnum[20];
    char   FMrelease[20];
    struct stat stbuf;
    struct stat stbuf1;
 
    while ( fgets(line, LENGTH, ifd ))
    {  
       /* initialization */
       desc[0]     = '\0';  pkgname[0]  = '\0';  pdtname[0]   = '\0';
       pdtsize[0]  = '\0';  platform[0] = '\0';  FMrelease[0] = '\0';
       fileline[0] = '\0';

       /* if products, then check install/pdts directory */
       if (!strncmp(prodName,"pdts",4))
       {    
           if ( sscanf( line,"%s%s%s%s%s%s",desc,pkgname,pdtname,
                    pdtsize, platform, FMrelease) == 6)
           {
               (void)sprintf(fileline,"%s/install/%s/%s_%s_%s.%s",
                         Proot,prodName,pdtname,platform,FMrelease,suffix);
               (void)sprintf(fileline1,"%s/install/pkgs/%s.%s",
                         Proot,pkgname,suffix);
           }
           else
           {
               (void)fprintf(stdout,"%sFormat Error of <%s>\n",PROGNAME,iFileNam);
                exitHdr(1);
           }

           
           if ( !strncmp(suffix,"ok",2)  )  /* suffix is ok */ 
           {
               /*
                * if .ok file does not exist in pdts directory, print out
                * the product line
                */
 
               if (stat(fileline, &stbuf) || stat(fileline1, &stbuf1))
                  (void)fprintf(stdout,"%s",line);
           }
           else                             /* suffix is nok */
           if ( !strncmp(suffix,"nok",3) )  /* suffix is nok    */

           {
                if (!stat(fileline, &stbuf))   /* exist */
                   (void)fprintf(stdout,"%s",line);
           }
       }  
           /* 
            * if pkgs, then check for install/pkgs directory
            */
       else if (!strncmp(prodName,"pkgs",4))
       {
           /* 
            * read a package line
            */
           if ( sscanf( line,"%s%s%s%s%s%s",desc,pkgname,pdtname,
                   FMrelease, CDnum, FSnum   ) == 6)
               (void)sprintf(fileline,"%s/install/%s/%s.%s",
                         Proot,prodName,pkgname,suffix);
           else
           {
               (void)fprintf(stdout,"%sFormat Error of <%s>\n",PROGNAME,iFileNam);
                exitHdr(1);
           }

           if ( !strncmp(suffix,"ok",2)  )  /* suffix is ok */
           {
               /*
                * if .ok file does not exist in pkgs directory, print out
                * the package line
                */

               if (stat(fileline, &stbuf))
                  (void)fprintf(stdout,"%s",line);
           }
           else                             /* suffix is nok */
           {
                /*
                * if .nok file exists in pkgs directory, print out
                * the package line
                */
 
                if (!stat(fileline, &stbuf))   /* exist */
                   (void)fprintf(stdout,"%s",line);
           }
       }            
    }
    return 0;
}

/*
 * fltrbit():
 * replace the 'bit' with a blank in the passed word and
 * chop word length to WORDLEN
 */       
char *fltrbit(word, bit)
char word[LENGTH+1];
char bit;
{
   int i = 0;
   int j = 0;

   j = strlen(word);
   while ( (i < j) && (i < WORDLEN)  )
   {
      if (word[i] == bit)
         word[i] = ' ';
      i++;
   }

   word[i] = '\0';
   return(word);
}

/* blankLine:
 *   0 not a blank line
 *   1 a blank line 
 */
int 
blankLine(line)
   char line[LENGTH+1];
{
   int i = 0;
   int j;

   j = strlen(line);
   while (i < j )
   {
      if ( line[i] != ' ' &&  line[i] != '\n' &&  line[i] != '\t' )
         return 1;
      i++;
   }
   return 0;
}

/*
 * case 3
 * case 5
 *  invPdts():
 *     Sflag: Don't print out the header          
 *     Read product lines from input file and display an inventory of 
 *     products installed, failed and available.
 */    
int invPdts(Sflag)
int Sflag;
{
    char   line[LENGTH+1];
    char   desc[LENGTH+1], pkgname[LENGTH+1], pdtname[LENGTH+1];
    char   fileOk[2*MAXPATHLEN+1];
    char   fileNok[2*MAXPATHLEN+1];
    char   pkgfileOk[2*MAXPATHLEN+1];
    char   pdtsize[LENGTH+1];
    char   platform[20];
    char   FMrelease[20];
    char   type[15];
    char   prev_prod[LENGTH +1];
    struct stat stbuf;
    struct stat stbuf1;
    char   *form1="---------------------------------------                     ";
    char   *form2="------ ----\n";
    if (!Sflag)  /* no suppress heading */
    {
       (void)fprintf(stdout,"%-55s%9s %9s\n","Product Description","size","status");
       (void)fprintf(stdout,"%s%s",form1,form2);
    }

    while ( fgets(line, LENGTH, ifd ))  /* read a line */ 
    {
         /*
          * initialization
          */
	 desc[0]     = '\0';  pkgname[0]  = '\0';  pdtname[0]   = '\0';
         pdtsize[0]  = '\0';  platform[0] = '\0';  FMrelease[0] = '\0';
         fileOk[0]   = '\0';  fileNok[0]  = '\0';  type[0]     = '\0';


         if ( sscanf( line,"%s%s%s%s%s%s",desc,pkgname,pdtname,
                    pdtsize, platform, FMrelease) == 6)
         {
            if (!strcmp(prev_prod, pdtname))
            {
              continue;
            }
 
            (void)sprintf(fileOk,"%s/install/pdts/%s_%s_%s.ok",
                         Proot,pdtname,platform,FMrelease);
            (void)sprintf(fileNok,"%s/install/pdts/%s_%s_%s.nok",
                         Proot,pdtname,platform,FMrelease);
            (void)sprintf(pkgfileOk,"%s/install/pkgs/%s.ok",
                         Proot,pkgname);

            /* 
             * if .ok exists in install/pdt directory, type is installed
             * if .nok exists in install/pdt directory, type is failed
             * else type is available
             */ 
            if (!stat(fileOk, &stbuf))   /* ok exist */
            {
               (void)strcpy(type,"installed"); /* load do not need list installed */
                if (stat(pkgfileOk, &stbuf1))   /* ok does not  exist */
                  (void)strcpy(type,"available"); /* load do not need list installed */
            } 
            else 
            if (!stat(fileNok,&stbuf))   /* nok exist */
            {
               (void)strcpy(type,"failed   ");
            }
            else
               (void)strcpy(type,"available");
   
             /* load do not need list installed */
            if ((caseNum == 3) && ( !strcmp(type,"installed")) )
            ;
            else   /* list installed and failed products */
            if ((caseNum == 5) && ( !strcmp(type,"available")) )
            ;
            else
            {
               strcpy(prev_prod,pdtname);
               if (Sflag)
                  (void)fprintf(stdout,"%s pkgname %s %s %s %s %s\n", desc,
                       pdtname,pdtsize, platform, FMrelease,type);
               else
               {
                  (void)strcpy(desc, fltrbit(desc, '~'));
                  (void)fprintf(stdout,"%-55s%9s %9s\n",desc,pdtsize,type);
               }
            }
        }    /* end of if scan == 6 */ 
        else 
        {
            (void)fprintf(stdout,"%sFormat Error of <%s>\n",PROGNAME,iFileNam);
             exitHdr(1);
        }    /* end of format error */
    }   /* end of while */
    return 0;
}       

/* 
 * case 4
 * Combine 3 open/close (pipe) to one open/close, replace '~'
 * with a blank in any word, and minimize column processing.
 *        replace code:
 *        1.   awk '{ '"$field"' }' $infile | tr '~' ' ' | {
 *              $columnize -n $gutterWidth $columns
 *              | $jsr Page
 * input file has 7 fields.
 */
int
fltr(bits, field)
char *bits;
int field;
{
   int i = 1;
   char   line[LENGTH+1];
   char   desc[LENGTH+1], pkgname[LENGTH+1], pdtname[LENGTH+1];
   char   pdtsize[LENGTH+1];
   char   platform[20];
   char   FMrelease[20];
   char   type[15];
   char   temp[LENGTH+1];

   (void)fprintf(stdout,"\n\n");
   while ( fgets(line, LENGTH, ifd ))
   {
      desc[0]     = '\0';  pkgname[0]  = '\0';  pdtname[0]   = '\0';
      pdtsize[0]  = '\0';  platform[0] = '\0';  FMrelease[0] = '\0';
      type[0]     = '\0';

       if ( sscanf( line,"%s%s%s%s%s%s%s",desc,pkgname,pdtname,
                    pdtsize, platform, FMrelease,type) )
       {
           desc[46] = '\0';
           if (bits)
               (void)strcpy(desc, fltrbit(desc, bits[0]));
          
           (void)sprintf(temp,"%d) ",i++);
           (void)fprintf(stdout,"%-5s",temp);
           if (field)
               (void)fprintf(stdout,"%-46s %-9s %s (%s)\n",desc,pdtsize,type,platform);
           else
           {
               if (strcmp(pkgname, "pkgname") ==0)
                 (void)sprintf(temp,"");
               else
                 (void)sprintf(temp,"(%s)",pkgname);
               (void)fprintf(stdout,"%-40s%-35s\n",desc, temp);
           }
       }
   }
}
      
/******************************************************************
	case 6: Sorts the allbundles.$Platform file and stores the
		results in sortallbundles.$platform.
******************************************************************/
#define PROD_NOS 1280
#define MAXLEN 1024
 
typedef struct
{
   char pdtname[LENGTH+1]; /*LENGTH is 255*/
   int index;
}pdtname_struct;

typedef struct
{
   char *desc;
   char *pdtsize;
   char *platform;
   char *FMrelease;
}pdtdetail_struct;

pdtname_struct *pdtname_arr[PROD_NOS];
pdtdetail_struct *pdt_arr[PROD_NOS];




list_products(Sflag)
int Sflag;
{
	
   struct stat i_stat,i2_stat;
   char dirname[2*MAXPATHLEN+1];
   char filename[2*MAXPATHLEN+1];
   int count;
   DIR *dp;			/*To Open the pdts directory*/
   struct dirent *pdtdir;	/*read the files in the pdts directory*/
   int i,file_count,ok_flag = 0;
   pdtname_struct *pdtfiles_arr[PROD_NOS];
/*
These variables are used when the pdts directory is being read
*/
   char platform[20];
   char FMrelease[20];
   char *p,*q,*r;
/*
if the product description does not exist in the merged bundles
and all bundles these variables are used
*/
   FILE *fp,*fopen();
   char line[MAXLEN+1];
   char oknok_filename[PROD_NOS][256];
   char *type;
   int ref;



   if( !iFileNam )
   {
	  (void)fprintf(stderr,"%sSpecify the first input file name (sorted bundles file)\n%s",PROGNAME, usage);
	exitHdr(1);
   }

   if( !iFileNam2 )
   {
	  (void)fprintf(stderr,"%sSpecify the second input file name(sorted allbundles file)\n%s",PROGNAME, usage);
	exitHdr(1);
   }
   if( !Proot )
   {
	  (void)fprintf(stderr,"%sIllegal value of Proot\n%s",PROGNAME, usage);
	exitHdr(1);
   }
   if (!vendor)
   {
	(void)fprintf(stderr,"%s:Illegal vendor name \n%s",PROGNAME,usage);
	exitHdr(1);
   }

   /*
	Generate the path of the pdts directory prior to opening it
        Try to open the Proot/install/pdts directory and list the files
        in that directory
   */

   (void)sprintf(dirname,"%s/install/pdts",Proot);
   if(NULL == (dp=opendir(dirname)))
   {
	(void)fprintf(stderr,"%sCould not open the directory:\n%s",PROGNAME,dirname);
	exitHdr(1);
   }

	count=read_file();
   /*
	Read the product directory
   */

	platform[0]='\0';
	FMrelease[0]='\0';

 	if(count >0)
        {
	    (void)strcpy(platform,pdt_arr[0]->platform);
	    (void)strcpy(FMrelease,pdt_arr[0]->FMrelease);
	}
   
	/*
	 read the pdts directory now. Look for .ok and .nok files
 	 with the same FMrelease and Platform as platform and FMrelease.
	*/

	i=0;
	/* to indicate that platform and release have
			  have been determined*/
	while(NULL != (pdtdir=readdir(dp)))
   	{
	   if(i == PROD_NOS)
	   {
   	      (void)fprintf(stderr,"%s: Listing Products (number of ok nok files more than  PROD_NOS)\n",PROGNAME);
   	      exitHdr(1);
	   }

	   if(count >0)
           {
	   if(!(p=strstr(pdtdir->d_name,vendor))|| 
			!(q=strstr(pdtdir->d_name,FMrelease)))
		continue;
	   }
	   else if(!(p=strstr(pdtdir->d_name,vendor))) 
		continue; 


       	   if(NULL == (pdtfiles_arr[i] = (pdtname_struct *)malloc(
         			sizeof(pdtname_struct))))
	   {
	      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
	      exitHdr(1);
	   }
	

	   if(p-pdtdir->d_name-1 >0)
	   {
		(void)strncpy(pdtfiles_arr[i]->pdtname,pdtdir->d_name,
						p-pdtdir->d_name-1);
	        pdtfiles_arr[i]->pdtname[p-pdtdir->d_name-1] = '\0';

    	        pdtfiles_arr[i]->index = i; 
		(void)strcpy(oknok_filename[i],pdtdir->d_name);
		i++;
	   }
	   else
	   {
		(void)fprintf(stderr,"%sCould not isolate product names\n",PROGNAME);
		exitHdr(1);
	   }
	   
   	}/*end of the while loop*/

        closedir(dp);

	file_count = i;

	if(file_count>0)
        {
	heap_sort(pdtfiles_arr,file_count);


	for(i=0;i<file_count;i++)
	{
 	   ref = 0;
           if(strstr(oknok_filename[pdtfiles_arr[i]->index],".ok"))
		type= "installed";
	   else
		type="failed";

           if(count >0)
           {
	   ref = binary_search(pdtfiles_arr[i],pdtname_arr,count);
	   if(ref>=0)
	   {
		ref=pdtname_arr[ref]->index;
           	if (Sflag)
           	(void)fprintf(stdout,"%s pkgname %s %s %s %s %s\n", 
			pdt_arr[ref]->desc,pdtfiles_arr[i]->pdtname,
			pdt_arr[ref]->pdtsize, pdt_arr[ref]->platform, 
			pdt_arr[ref]->FMrelease,type);
            	else
            	{
              	   (void)strcpy(pdt_arr[ref]->desc, 
				fltrbit(pdt_arr[ref]->desc, '~'));
                   (void)fprintf(stdout,"%-55s%9s %9s\n",
			 pdt_arr[ref]->desc,pdt_arr[ref]->pdtsize,type);
            	}
	    }/*end of the ref>=0 if stmt*/
 	    }/*end of if count >0 if stmt*/

            /*If after this if stmt ref >=0 it will not enter
              the next if stmt. If it does not enter the
              previous if stmt then count ==0 and it will enter this
              if stmt
            */

	   if(ref<0 || count==0)
	   {

	        (void)sprintf(filename,"%s/install/pdts/%s",Proot,
			oknok_filename[pdtfiles_arr[i]->index]);
	        if((fp=fopen(filename,"r")))
		{
		   	if(fgets(line,MAXLEN,fp))/*only 1 stmt under */
			if(Sflag)
			{
			   char *p;
			   if(p=strrchr(line,'\n'))
				*p = '\0';
			   (void)fprintf(stdout,"%s %s\n",line,type);
			}
			else
			{
			   char desc[LENGTH];
			   char pkgname[LENGTH];
	  		   char pdtname[LENGTH];
			   char pdtsize[15];
			   char platform[15];
			   char FMrelease[15];

			   if(sscanf(line,"%s%s%s%s%s%s",
				desc,pkgname,pdtname,pdtsize,platform,
							  FMrelease)==6)
			   {
              			(void)strcpy(desc, fltrbit(desc, '~'));
              			(void)fprintf(stdout,"%-55s%9s %9s\n",
						     desc,pdtsize,type);
			   }
			}/*end of Sflag if stmt else branch*/
		       (void)fclose(fp);
		}/*end of fopen if stmt else branch*/
	   }/*end of ref<0 if stmt*/

	}/*end of the for loop*/
     }/*End of if file_count>0*/
   /*
	Free memory
   */

   if(file_count >0)
   {
      if(pdtfiles_arr != NULL)
      {
	for(i=0;i<file_count;i++)
	    if(pdtfiles_arr[i] != NULL)
		free(pdtfiles_arr[i]);
      }
   }

   if (count>0)
   {

      if(pdtname_arr != NULL)
      {
	for(i=0;i<count;i++)
	    if(pdtname_arr[i] != NULL)
		free(pdtname_arr[i]);
      }
      if(pdt_arr != NULL)
      {
	for(i=0;i<count; i++)
	{
	   if(pdt_arr[i] != NULL)
	   {
	   free(pdt_arr[i]->desc);
	   free(pdt_arr[i]->pdtsize);
	   free(pdt_arr[i]->platform);
	   free(pdt_arr[i]->FMrelease);
	   free(pdt_arr[i]);
	   }
	}
      }
   }

}/*End of function list_products*/

  
int binary_search(str,arr,count)
char *str;
pdtname_struct **arr;
int count;
{
	int i=0,j,k;
	j=count-1;
	

	while(i<j)
	{
	   k = (i+j)/2;
	   if(strcmp(str,arr[k]->pdtname)<0)
		j=k-1;
	   else
	   {
		if(strcmp(str,arr[k+1]->pdtname)>=0)
		   i=k+1;
		else 
		{
		   i=k;
		   j=k;
		}
	   }
	}

	if(strcmp(str,arr[i]->pdtname) == 0)
	   return i;
	else
	   return -1;
}



/*****************************************************************
*heap_sort():
*	sorts the pdtname_arr[]. This sort is not a generic sort
*        but will sort only structures of type pdtname_struct.
*        This is a lot faster than the normal system 'sort'
*	command.
*	CREATED BY: Hariraj Dyal
*	CREATION DATE: 7th June 1994
*	MODIFIED BY:
*	MODIFICATION DATE:
*	COMMENTS:
****************************************************************/



heap_sort(arr,size)
pdtname_struct **arr;
int size;
{
	int i,temp1;
	char temp[LENGTH];



	for (i=size/2;i>=0;i--)
		heapify(arr,i,size);

	for(i=size-1;i>0;i--)
	{
		(void)strcpy(temp , arr[0]->pdtname);
		(void)strcpy(arr[0]->pdtname , arr[i]->pdtname);
		(void)strcpy(arr[i]->pdtname, temp);
		temp1= arr[0]->index;
		arr[0]->index = arr[i]->index;
		arr[i]->index = temp1;
		heapify(arr,0,i);
	}
}


/*****************************************************************
*heapify()
*	This makes sure that the the node of a binary tree
*	and its subtrees are heaps
*	CREATED BY: Hariraj Dyal
*	CREATION DATE: 7th June 1994
*	MODIFIED BY:
*	MODIFICATION DATE:
*	COMMENTS:
****************************************************************/

heapify(arr,index,size)
pdtname_struct **arr;
int index;
int size;
{
	
	char temp[LENGTH];
	int l,r,largest,temp1;

	largest = index;

	do
	{
		index = largest;
		l = 2*index+1;
		r = 2*index+2;


		if(l< size )
		{
			if((strcmp(arr[l]->pdtname , arr[index]->pdtname)>0))
				largest=l;
			else
				largest=index;
		}
		else
			largest=index;

		if(r<size)
			if((strcmp(arr[r]->pdtname ,arr[largest]->pdtname)>0))
				largest=r;
		(void)strcpy(temp , arr[index]->pdtname);
		(void)strcpy(arr[index]->pdtname , arr[largest]->pdtname);
		(void)strcpy(arr[largest]->pdtname, temp);
		temp1= arr[index]->index;
		arr[index]->index = arr[largest]->index;
		arr[largest]->index = temp1;
		
	}while(largest != index); 
}

/***************************************************************
*read_file():
*	This function is called by list_products when a sorted
*	allbundles.Platform file exists. It reads the sorted file
*	sortallbundles.platform (the output file) into memory
*	CREATED BY: Hariraj Dyal
*	CREATION DATE: 7th June 1994
*	MODIFIED BY:
*	MODIFICATION DATE:
*	COMMENTS:
***************************************************************/
		
int read_file()
{
   FILE *fopen(),*ifp,*ifp2;
   char line[LENGTH+1];
   char desc[LENGTH+1],pkgname[LENGTH+1],pdtname[LENGTH+1];
   char pdtsize[20],platform[20],FMrelease[20];
   int i,count;
   int ref;
   int ok_flag=0;
   
   desc[0]     = '\0';  pkgname[0]  = '\0';  pdtname[0]   = '\0';
   pdtsize[0]  = '\0';  platform[0] = '\0';  FMrelease[0] = '\0';



   i=0;
   count =0;
   if((ifp = fopen(iFileNam,"r")))
   {
   while(fgets(line,LENGTH,ifp))
   {
	if(i == PROD_NOS)
	{
   	      (void)fprintf(stderr,"%s: Listing Products (number of products more than PROD_NOS)\n",PROGNAME);
   	      exitHdr(1);
	}
	if(sscanf(line,"%s%s%s%s%s%s",desc,pkgname,pdtname,pdtsize,
			platform,FMrelease) == 6)
	{
           if(NULL == (pdtname_arr[i] = (pdtname_struct *)malloc(
   			sizeof(pdtname_struct))))
   	   {
   	      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
   	      exitHdr(1);
   	   }
       	   (void)strcpy(pdtname_arr[i]->pdtname,pdtname);
   	      pdtname_arr[i]->index = i;
   
   	   if(NULL == (pdt_arr[i] = (pdtdetail_struct *)malloc(sizeof(pdtdetail_struct))))
   	   {
   	      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
   	      exitHdr(1);
   	   }
   	   if(NULL==(pdt_arr[i]->desc = 
   		(char *)malloc(strlen(desc)+1))||
   		(NULL == (pdt_arr[i]->pdtsize=
   		(char*)malloc(strlen(pdtsize)+1)))||
   		(NULL == (pdt_arr[i]->platform = 
   		(char*)malloc(strlen(platform)+1)))||
   		(NULL == (pdt_arr[i]->FMrelease = 
   		(char*)malloc(strlen(FMrelease)+1))))
   	   {
   	      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
   	      exitHdr(1);
   	   }
   
   	   (void)strcpy(pdt_arr[i]->desc,desc);
   	   (void)strcpy(pdt_arr[i]->pdtsize,pdtsize);
   	   (void)strcpy(pdt_arr[i]->platform,platform);
   	   (void)strcpy(pdt_arr[i]->FMrelease,FMrelease);
   	   i++;
	}/*End of the sscanf if statement*/
   }/*End of the while loop*/

   count = i;
   if(count >0)
	heap_sort(pdtname_arr,count);

   if(ifp)
	(void)fclose(ifp);
   }/*End of the open iFileNam*/

   if((ifp2 = fopen(iFileNam2,"r")))
   {
	if(i == PROD_NOS)
	{
   	      (void)fprintf(stderr,"%s: Listing Products (number of products more than PROD_NOS)\n",PROGNAME);
   	      exitHdr(1);
	}
	while(fgets(line,MAXLEN,ifp2))
	{
	   if(sscanf(line,"%s%s%s%s%s%s",desc,pkgname,pdtname,pdtsize,
			platform,FMrelease) == 6)
	   {	   
	       if(count >0)
	         ref = binary_search(pdtname,pdtname_arr,count);

		if(ref<0 || count == 0)  /*if pdt not in bundles*/
		{
    		   if(NULL == (pdtname_arr[i] = (pdtname_struct *)malloc(
		   		sizeof(pdtname_struct))))
		   {
		      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
		      if(ifp2)
	   		(void)fclose(ifp2);
		      exitHdr(1);
		   }
		   (void)strcpy(pdtname_arr[i]->pdtname,pdtname);
		   pdtname_arr[i]->index = i;

   
        	   if(NULL == (pdt_arr[i] = 
		  (pdtdetail_struct *)malloc(sizeof(pdtdetail_struct))))
		   {
		      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
		      if(ifp2)
	   		(void)fclose(ifp2);
		      exitHdr(1);
		   }

		   if(NULL==(pdt_arr[i]->desc = 
			(char *)malloc(strlen(desc)+1))||
			(NULL == (pdt_arr[i]->pdtsize=
			(char*)malloc(strlen(pdtsize)+1)))||
			(NULL == (pdt_arr[i]->platform = 
			(char*)malloc(strlen(platform)+1)))||
			(NULL == (pdt_arr[i]->FMrelease = 
			(char*)malloc(strlen(FMrelease)+1))))
		   {
		      (void)fprintf(stderr,"%sNot Enough memory Quitting\n",PROGNAME);
		      if(ifp2)
	   		(void)fclose(ifp2);
		      exitHdr(1);
		   }

		   (void)strcpy(pdt_arr[i]->desc,desc);
		   (void)strcpy(pdt_arr[i]->pdtsize,pdtsize);
		   (void)strcpy(pdt_arr[i]->platform,platform);
		   (void)strcpy(pdt_arr[i]->FMrelease,FMrelease);
		   i++;

		}/*end of ref<0 if stmt*/
	   }/*end of sscanf if stmt*/
	}/*end of while loop*/
	if(count != i)
	{
           count = i;
	   heap_sort(pdtname_arr,count);
	}
  
    }/*End of if it can open iFileNam2 file*/
    return count;
}
		

	

/*
** Main
*/
main(argc, argv)
int argc;
char *argv[]; 
{
   char    *keys =     (char *)0;
   int     args  =     0;
   int     Sflag     = 0;
   char    *bits     = (char *)0;
   int     field     = 0;

   caseNum=0;		/* case number             */
   iFileNam = (char *)0;  /* input file name         */
   prodName="pdts";       /* pdts or pkgs level      */
   suffix="ok";           /* suffix file .ok or .nok */

   usage=
"process_file [1|2|3|4|5|6 I input2] [p Proot]  i input [[ k [pkgs|pdts][ok|nok]] | S | [f|F bit]]\n";

   if ( !(keys = argv[++args]) )
   {
       (void)fprintf( stderr,"%sIllegal empty case numer\n%s",PROGNAME, usage );
       exitHdr( 1 );
   } 

   
   while (*keys)
   {
	switch (*keys )
        {  
           case '1': case '2': case '3': case '4': case '5': case '6': 
		caseNum = atoi( keys );
		break; 
           case 'i' :
                if ( !(iFileNam = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty input file name\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
                break;
           case 'p' :
                if ( !(Proot =argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty Proot\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
		break;
	   case 'k' :
		if ( !(prodName = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty pdts/pkgs name\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
		if ( !(suffix  = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty suffix\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
		break;
           case 'f' : 
                if ( !(bits = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty bit\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
                break;
           case 'F' :
                field = 1;  
                if ( !(bits = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty bit\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
                break;
           case 'S' :
                   Sflag = 1;
                break;

	   case 'I' :
                if ( !(iFileNam2 = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty second input file name\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
                break;
	
	   case 'v' :
                if ( !(vendor = argv[++args]) )
                {   (void)fprintf(stderr,"%sIllegal empty vendor name\n%s",PROGNAME, usage);
                    exitHdr(1);
                }
                break;
           default:
                (void)fprintf( stderr,"%s%s",PROGNAME,  usage );
                exitHdr(1);
        }
	if ( (args + 2) <= argc )
           keys = argv[++args]; 
        else
           keys[0] = '\0';
     }
 
     if ( !Proot)
     {
        (void)fprintf(stderr,"%sIllegal empty Proot\n",PROGNAME);
        exitHdr(1);
     }

     if ( !iFileNam )
     {
        (void)fprintf(stderr,"%sIllegal empty input file name\n",PROGNAME);
        exitHdr(1);
     }

   if(caseNum != 6)
     if ( !(ifd = fopen( iFileNam, "r")))
     {
        (void)fprintf(stderr,"%sCannot open input file <%s>\n",PROGNAME,iFileNam);
        exitHdr(1);
     }

     if (caseNum == 1) 
        (void)checkLoad();
     else
     if (caseNum == 2)
        (void)statusFltr();
     else
     if (caseNum == 3)
	(void)invPdts(Sflag);
     else
     if (caseNum == 4) 
        (void)fltr(bits,field);
     else
     if (caseNum == 5) 
        (void)invPdts(Sflag); 
     else
	(void)list_products(Sflag);
	



   /*
     Hariraj: For case 6 it expects 2 input file names filename 
     followed by i is the sorted bundles file and one after
     2 is the sorted allbundles file
   */

     if (ifd)
        (void)fclose(ifd);
     return 0;
}
