home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / alsrc121.lzh / ALGEN.C next >
C/C++ Source or Header  |  1993-09-23  |  43KB  |  1,057 lines

  1. /* ALGEN.C -- Copyright 1992-93 -- By Richard Butler -- EUROPA Software
  2.  
  3.     This code carries no warranties, whether expressed or implied.
  4.  
  5.     This code, it's listing, object file, and executable may not be
  6.     distributed in any modified form.
  7.  
  8.     Thanks to Harvey Parisien for his HLIST program upon which ALGEN is based.
  9.  
  10.     Thanks to Erik Vanriper for releasing the source for his FILELIST program.
  11.     It was a very useful reference while writing ALGEN.
  12.  
  13.     ---------------------------------------------------------------------------
  14.  
  15.     Richard Butler
  16.     BBS: (504) 652-4916
  17.     Fidonet 1:396/61
  18.     ibmNET 40:4372/61
  19.     OS2Net 81:10/20
  20.  
  21. */
  22.  
  23. #define INCL_NOPMAPI
  24. #define INCL_DOSFILEMGR
  25.  
  26. #include <stdio.h>
  27. #include <time.h>
  28. #include <sys\types.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <ctype.h>
  32. #include <os2.h>
  33. #include <errno.h>
  34. #include "mstruct.h"
  35. #include "fb.h"
  36.  
  37. #define VERSION "ALGEN v1.21 - (c)1992-93 by Richard Butler"
  38. #define MAXLSIZE 512
  39.  
  40. typedef struct _areabuf {
  41.     char path[80];
  42.     char name[10];
  43.     char desc[80];
  44.     char files_bbs[80];
  45.     unsigned file_count;
  46.     unsigned new_file_count;
  47.     unsigned long area_bytes;
  48.     unsigned long new_area_bytes;
  49. } AREABUF;
  50.  
  51. typedef struct _config {
  52.     char system_name[40];
  53.     char header_file[80];
  54.     char new_header_file[80];
  55.     int new_days;
  56.     char list_file[80];
  57.     char new_list_file[80];
  58.     char stripflags;
  59.     char noibmchars;
  60.     char showmaxnames;
  61.     char noemptyareas;
  62.     char indent;
  63.     char use_fidx;
  64.     char showsummary;
  65.     char ignorebaddates;
  66.     char areadat_path[80];
  67. } CONFIG;
  68.  
  69. int Check_Exclude(char *key, char **list, int num);
  70.  
  71. int Check_Empty_Area(char *file_path);
  72.  
  73. char *Get_Arg(char *string);
  74.  
  75. int GetFileInfo(FIDX **f_idx, char *file_name, ULONG *file_size, FDATE *file_date, char use_fidx, unsigned idx_recs, FILE *fp, int fdat_length);
  76.  
  77. FIDX **LoadFIDX(char *file_path, unsigned *num_recs);
  78.  
  79. unsigned SearchFIDX(FIDX **f_idx, int num_recs, char *key);
  80.  
  81. void strsort (FIDX **array, size_t array_size);
  82.  
  83. FILE *SH_fopen(char *filename, char *mode);
  84.  
  85. char *whitespace = " \t\n\r";
  86.  
  87. main(int argc, char *argv[])
  88. {
  89.     AREABUF **area;
  90.     FIDX **files_idx;
  91.     CONFIG cfg;
  92.     struct tm current_date;
  93.     struct tm new_date;
  94.     struct tm *tm_ptr;
  95.     time_t current_time;
  96.     time_t new_time;
  97.     time_t file_time;
  98.     unsigned long ws_new_date;
  99.     unsigned long ws_current_date;
  100.     unsigned long ws_file_date;
  101.     unsigned total_count = 0;
  102.     unsigned total_new_count = 0;
  103.     unsigned long total_bytes = 0;
  104.     unsigned long total_new_bytes = 0;
  105.     FILE *config_file_p;
  106.     FILE *header_file_p;
  107.     FILE *list_file_p;
  108.     FILE *new_list_file_p = NULL;
  109.     FILE *fp;
  110.     char config_file[80] = "ALGEN.CFG";     /* Default config file */
  111.     int i = 0;
  112.     size_t len;
  113.     char io_buf[MAXLSIZE];
  114.     char *ptr;
  115.     char *ws_ptr;
  116.     int num_areas = 0;
  117.     char file_path[128];
  118.     char file_path2[128];
  119.     char fdat_path[128];
  120.     char fidx_path[128];
  121.     char file_name[13];
  122.     unsigned char new;
  123.     char *fd_ptr;
  124.     int length;
  125.     APIRET rc;
  126.     char buffer[80];
  127.     char *p_buffer;
  128.     char f_date[25];
  129.     FILE *area_fp;
  130.     struct _area areadat;
  131.     char **exclude;
  132.     int num_exclude = 0;
  133.     char drive[3];
  134.     char dir[66];
  135.     char fname[9];
  136.     char ext[5];
  137.     char temp_fl[80];
  138.     char temp_nfl[80];
  139.     char area_banner[256];
  140.     int x;
  141.     char file_desc[MAXLSIZE];
  142.     FDATE file_date;
  143.     ULONG file_size;
  144.     FDAT f_dat;
  145.     FILE *fdat_fp;
  146.     unsigned idx_recs;
  147.     int fdat_length;
  148.  
  149.     printf("\n╓─────────────────────────────────────────────────────────────────────────────╖");
  150.     printf("\n║ %-58s Fidonet 1:396/61 ║",VERSION);
  151.     printf("\n╙─────────────────────────────────────────────────────────────────────────────╜");
  152.     fflush(stdout);
  153.     if((area = malloc(sizeof(AREABUF *))) == NULL) {
  154.         printf("\n\nNot enough memory!  Exiting....\n");
  155.         exit(255);
  156.     }
  157.     current_time = time(NULL);
  158.     tm_ptr = localtime(¤t_time);
  159.     current_date = *tm_ptr;
  160.     ws_current_date = ((current_date.tm_year * 10000) + ((current_date.tm_mon + 1) * 100) + current_date.tm_mday);
  161.     strftime(f_date,24,"%a %b %d, %Y %H:%M",¤t_date);
  162.     if(argc > 1)            /* assume that argv[1] is a valid config file */
  163.         strncpy(config_file, argv[1], 79);
  164.     if((config_file_p = fopen(config_file,"r")) == NULL) {
  165.         printf("\n\nError opening ConfigFile '%s'!  Exiting....\n",config_file);
  166.         exit(255);
  167.     }
  168.  
  169. /*---------------------------------------------------------------------------*/
  170.     /* Parse config file */
  171.  
  172.     *cfg.system_name = '\0';
  173.     *cfg.header_file = '\0';
  174.     *cfg.new_header_file = '\0';
  175.     cfg.new_days = 14;
  176.     *cfg.list_file = '\0';
  177.     *cfg.new_list_file = '\0';
  178.     cfg.stripflags = FALSE;
  179.     cfg.noibmchars = FALSE;
  180.     cfg.showmaxnames = FALSE;
  181.     cfg.noemptyareas = FALSE;
  182.     cfg.indent = FALSE;
  183.     cfg.use_fidx = FALSE;
  184.     cfg.showsummary = FALSE;
  185.     cfg.ignorebaddates = FALSE;
  186.     *cfg.areadat_path = '\0';
  187.  
  188.     printf("\n\nReading %s....",config_file);
  189.     fflush(stdout);
  190.     while(fgets(io_buf,MAXLSIZE,config_file_p)) {
  191.         if(ptr = strchr(io_buf,'\n'))
  192.             *ptr = '\0';
  193.         if(io_buf[0] == '\0')
  194.             continue;
  195.         ws_ptr = io_buf + strspn(io_buf,whitespace);
  196.         if(*ws_ptr == '\0' || *ws_ptr == ';')
  197.             continue;
  198.         sscanf(ws_ptr,"%79s",&buffer);
  199.         for(i = 0; buffer[i] != '\0'; i++)
  200.             buffer[i] = toupper(buffer[i]);
  201.  
  202.         if(strcmp("SYSTEM",buffer) == 0) {
  203.             ptr = Get_Arg(ws_ptr);
  204.             strncpy(cfg.system_name,ptr,39);
  205.         }
  206.         else if(strcmp("HEADER",buffer) == 0) {
  207.             ptr = Get_Arg(ws_ptr);
  208.             strncpy(cfg.header_file,ptr,79);
  209.         }
  210.         else if(strcmp("NEWHEADER",buffer) == 0) {
  211.             ptr = Get_Arg(ws_ptr);
  212.             strncpy(cfg.new_header_file,ptr,79);
  213.         }
  214.         else if(strcmp("NEWDAYS",buffer) == 0) {
  215.             ptr = Get_Arg(ws_ptr);
  216.             cfg.new_days = atoi(ptr);
  217.             new_time = (current_time - (cfg.new_days * 86400));
  218.             tm_ptr = localtime(&new_time);
  219.             new_date = *tm_ptr;
  220.             ws_new_date = ((new_date.tm_year * 10000) + ((new_date.tm_mon + 1) * 100) + new_date.tm_mday);
  221.         }
  222.         else if(strcmp("INDENT",buffer) == 0) {
  223.             ptr = Get_Arg(ws_ptr);
  224.             cfg.indent = atoi(ptr);
  225.             if(cfg.indent < 0)
  226.                 cfg.indent = 0;
  227.             if(cfg.indent > 16)
  228.                 cfg.indent = 16;
  229.         }
  230.         else if(strcmp("FILELIST",buffer) == 0) {
  231.             ptr = Get_Arg(ws_ptr);
  232.             strncpy(cfg.list_file,ptr,79);
  233.         }
  234.         else if(strcmp("NEWFILELIST",buffer) == 0) {
  235.             ptr = Get_Arg(ws_ptr);
  236.             strncpy(cfg.new_list_file,ptr,79);
  237.         }
  238.         else if(strcmp("STRIPFLAGS",buffer) == 0) {
  239.             cfg.stripflags = TRUE;
  240.         }
  241.         else if(strcmp("NOIBMCHARS",buffer) == 0) {
  242.             cfg.noibmchars = TRUE;
  243.         }
  244.         else if(strcmp("SHOWMAXNAMES",buffer) == 0) {
  245.             cfg.showmaxnames = TRUE;
  246.         }
  247.         else if(strcmp("NOEMPTYAREAS",buffer) == 0) {
  248.             cfg.noemptyareas = TRUE;
  249.         }
  250.         else if(strcmp("USEFIDX",buffer) == 0) {
  251.             cfg.use_fidx = TRUE;
  252.         }
  253.         else if(strcmp("SHOWSUMMARY",buffer) == 0) {
  254.             cfg.showsummary = TRUE;
  255.         }
  256.         else if(strcmp("IGNOREBADDATES",buffer) == 0) {
  257.             cfg.ignorebaddates = TRUE;
  258.         }
  259.         else if(strcmp("MAXAREAS",buffer) == 0) {
  260.             ptr = Get_Arg(ws_ptr);
  261.             strncpy(cfg.areadat_path,ptr,79);
  262.         }
  263.         else if(strcmp("AREAINCLUDE",buffer) == 0) {
  264.             num_areas = 0;
  265.             while(fgets(io_buf,MAXLSIZE,config_file_p) != NULL) {
  266.                 if(ptr = strchr(io_buf,'\n'))
  267.                     *ptr = '\0';
  268.                 if(io_buf[0] == '\0')
  269.                     continue;
  270.                 ws_ptr = io_buf + strspn(io_buf,whitespace);
  271.                 if(*ws_ptr == '\0' || *ws_ptr == ';')
  272.                     continue;
  273.                 sscanf(ws_ptr,"%79s",&buffer);
  274.                 for(i = 0; buffer[i] != '\0'; i++)
  275.                     buffer[i] = toupper(buffer[i]);
  276.                 if(strcmp("END",buffer) == 0)
  277.                     break;
  278.                 if((area[num_areas] = malloc(sizeof(AREABUF))) == NULL) {
  279.                     printf("\n\nNot enough memory!  Exiting....");
  280.                     exit(255);
  281.                 }
  282.                 if((area = realloc(area,((num_areas + 2) * sizeof(AREABUF *)))) == NULL) {
  283.                     printf("\n\nNot enough memory!  Exiting....");
  284.                     exit(255);
  285.                 }
  286.                 strncpy(area[num_areas]->path,ws_ptr,79);
  287.                 len = strcspn(area[num_areas]->path,whitespace);
  288.                 area[num_areas]->path[len] = '\0';
  289.                 if(area[num_areas]->path[len - 1] != '\\')
  290.                     strncat(area[num_areas]->path,"\\",79 - len);
  291.                 ptr = Get_Arg(ws_ptr);
  292.                 strncpy(area[num_areas]->desc,ptr,79);
  293.                 if(ptr = strchr(area[num_areas]->desc, '^')) {
  294.                     *ptr = '\0';
  295.                 }
  296.                 if(ptr = strchr(ws_ptr, '^')) {
  297.                     strncpy(area[num_areas]->files_bbs,++ptr,79);
  298.                 }
  299.                 else {
  300.                     strcpy(area[num_areas]->files_bbs,area[num_areas]->path);
  301.                     strncat(area[num_areas]->files_bbs,"FILES.BBS",78 - len);
  302.                 }
  303.                 area[num_areas]->name[0] = '\0';
  304.                 num_areas++;
  305.             }
  306.         }
  307.         else if(strcmp("END",buffer) == 0) {
  308.             continue;
  309.         }
  310.         else if(strcmp("AREAEXCLUDE",buffer) == 0) {
  311.             num_exclude = 0;
  312.             if((exclude = malloc(sizeof(char *))) == NULL) {
  313.                 printf("\n\nNot enough memory!  Exiting....\n");
  314.                 exit(255);
  315.             }
  316.             while(fgets(io_buf,MAXLSIZE,config_file_p) != NULL) {
  317.                 if(ptr = strchr(io_buf,'\n'))
  318.                     *ptr = '\0';
  319.                 if(io_buf[0] == '\0')
  320.                     continue;
  321.                 ws_ptr = io_buf + strspn(io_buf,whitespace);
  322.                 if(*ws_ptr == '\0' || *ws_ptr == ';')
  323.                     continue;
  324.                 sscanf(ws_ptr,"%79s",&buffer);
  325.                 for(i = 0; buffer[i] != '\0'; i++)
  326.                     buffer[i] = toupper(buffer[i]);
  327.                 if(strcmp("END",buffer) == 0)
  328.                     break;
  329.                 if((exclude[num_exclude] = malloc(sizeof(areadat.name))) == NULL) {
  330.                     printf("\n\nNot enough memory!  Exiting....");
  331.                     exit(255);
  332.                 }
  333.                 if((exclude = realloc(exclude,((num_exclude + 2) * sizeof(char *)))) == NULL) {
  334.                     printf("\n\nNot enough memory!  Exiting....");
  335.                     exit(255);
  336.                 }
  337.                 strncpy(exclude[num_exclude],buffer,39);
  338.                 num_exclude++;
  339.             }
  340.         }
  341.         else if(strcmp("END",buffer) == 0) {
  342.             continue;
  343.         }
  344.         else {
  345.             printf("\n\nUnknown Keyword '%s'  Exiting....\n",buffer);
  346.             exit(255);
  347.         }
  348.     }
  349.     fclose(config_file_p);
  350.  
  351.     /* Read Area.Dat */
  352.  
  353.     if(cfg.areadat_path[0] != '\0') {
  354.         if((area_fp = SH_fopen(cfg.areadat_path,"rb")) == NULL) {
  355.             printf("\n\nError opening MaxAreas '%s'!  Exiting....\n",cfg.areadat_path);
  356.             exit(255);
  357.         }
  358.         printf("\nReading %s....",cfg.areadat_path);
  359.         fflush(stdout);
  360.         fread(&areadat,sizeof(struct _area),1,area_fp);
  361.         length = areadat.struct_len;
  362.         for(i = 0; !feof(area_fp); i++) {
  363.             fseek(area_fp,i*(long)length,SEEK_SET);
  364.             rc = fread(&areadat,sizeof(struct _area),1,area_fp);
  365.             if(rc != 0 && areadat.filepath[0] != '\0' && areadat.filepath[0] != ' ' &&
  366.                Check_Exclude(areadat.name,exclude,num_exclude) != 1) {
  367.                 if((area[num_areas] = malloc(sizeof(AREABUF))) == NULL) {
  368.                     printf("\n\nNot enough memory!  Exiting....");
  369.                     exit(255);
  370.                 }
  371.                 if((area = realloc(area,((num_areas + 2) * sizeof(AREABUF *)))) == NULL) {
  372.                     printf("\n\nNot enough memory!  Exiting....");
  373.                     exit(255);
  374.                 }
  375.                 strncpy(area[num_areas]->path,areadat.filepath,79);
  376.                 len = strcspn(area[num_areas]->path,whitespace);
  377.                 area[num_areas]->path[len] = '\0';
  378.                 if(area[num_areas]->path[len - 1] != '\\')
  379.                     strncat(area[num_areas]->path,"\\",79 - len);
  380.                 if(areadat.fileinfo[0] != '\0' && areadat.fileinfo[0] != ' ') {
  381.                     if(cfg.showmaxnames) {
  382.                         strncpy(area[num_areas]->name,areadat.name,9);
  383.                     }
  384.                     else {
  385.                         area[num_areas]->name[0] = '\0';
  386.                     }
  387.                     strncpy(area[num_areas]->desc,areadat.fileinfo,79);
  388.                 }
  389.                 if(areadat.filesbbs[0] != '\0' && areadat.filesbbs[0] != ' ') {
  390.                     strncpy(area[num_areas]->files_bbs,areadat.filesbbs,79);
  391.                 }
  392.                 else {
  393.                     strcpy(area[num_areas]->files_bbs,area[num_areas]->path);
  394.                     strncat(area[num_areas]->files_bbs,"FILES.BBS",78 - len);
  395.                 }
  396.                 num_areas++;
  397.             }
  398.         }
  399.         fclose(area_fp);
  400.     }
  401.  
  402.     /* free memory used by exclude array */
  403.  
  404.     if(num_exclude != 0) {
  405.         for(i = num_exclude - 1; i >= 0; i--) {
  406.             free(exclude[i]);
  407.         }
  408.         free(exclude);
  409.     }
  410.  
  411. /*---------------------------------------------------------------------------*/
  412.  
  413.     printf("\n\nProcessing....\n");
  414.     fflush(stdout);
  415.  
  416.     /* open output files */
  417.  
  418.     if(cfg.list_file[0]) {
  419.         _splitpath(cfg.list_file,drive,dir,fname,ext);
  420.         strcpy(ext,".$$$");
  421.         _makepath(temp_fl,drive,dir,fname,ext);
  422.     }
  423.     else {
  424.         printf("\n\nA FileList name is required!  Exiting....\n");
  425.         exit(255);
  426.     }
  427.  
  428.     if((list_file_p = fopen(temp_fl,"w")) == NULL) {
  429.         printf("\n\nError opening FileList '%s'!  Exiting....\n",temp_fl);
  430.         exit(255);
  431.     }
  432.     if(cfg.new_list_file[0]) {
  433.         _splitpath(cfg.new_list_file,drive,dir,fname,ext);
  434.         strcpy(ext,".###");
  435.         _makepath(temp_nfl,drive,dir,fname,ext);
  436.         if((new_list_file_p = fopen(temp_nfl,"w")) == NULL) {
  437.             printf("\n\nError opening NewFileList '%s'!  Exiting....\n",temp_nfl);
  438.             exit(255);
  439.         }
  440.     }
  441.     if(cfg.header_file[0]) {
  442.         if((header_file_p = fopen(cfg.header_file,"r")) != NULL) {
  443.             while(fgets(io_buf,MAXLSIZE,header_file_p) != NULL)
  444.                 fputs(io_buf,list_file_p);
  445.             fclose(header_file_p);
  446.         }
  447.         else {
  448.             printf("\nError opening Header '%s'!  Continuing....\n",cfg.header_file);
  449.             fflush(stdout);
  450.         }
  451.     }
  452.     if(cfg.new_header_file[0] && new_list_file_p) {
  453.         if((header_file_p = fopen(cfg.new_header_file,"r")) != NULL) {
  454.             while(fgets(io_buf,MAXLSIZE,header_file_p) != NULL)
  455.                 fputs(io_buf,new_list_file_p);
  456.             fclose(header_file_p);
  457.         }
  458.         else {
  459.             printf("\nError opening NewHeader '%s'!  Continuing....\n",cfg.new_header_file);
  460.             fflush(stdout);
  461.         }
  462.     }
  463.  
  464.     if(cfg.noibmchars) {
  465.         fprintf(list_file_p,"+-----------------------------------------------------------------------------+\n");
  466.         fprintf(list_file_p,"|        This is a complete list of all files available on this system        |\n");
  467.         fprintf(list_file_p,"|                                                                             |\n");
  468.         sprintf(io_buf,"|   File dates followed by a * are < than %d days old, which is >= %.2d-%.2d-%d",cfg.new_days,(new_date.tm_mon + 1),new_date.tm_mday,new_date.tm_year);
  469.         strcat(io_buf,"          ");
  470.         io_buf[78] = '|';
  471.         io_buf[79] = '\0';
  472.         fprintf(list_file_p,"%s\n",io_buf);
  473.         fprintf(list_file_p,"|                                                                             |\n");
  474.         fprintf(list_file_p,"| %-53s%s |\n",cfg.system_name,f_date);
  475.         fprintf(list_file_p,"+-----------------------------------------------------------------------------+\n");
  476.         fprintf(list_file_p," %-60s Fidonet 1:396/61 \n\n",VERSION);
  477.     }
  478.     else {
  479.         fprintf(list_file_p,"╓─────────────────────────────────────────────────────────────────────────────╖\n");
  480.         fprintf(list_file_p,"║        This is a complete list of all files available on this system        ║\n");
  481.         fprintf(list_file_p,"║                                                                             ║\n");
  482.         sprintf(io_buf,"║   File dates followed by a * are < than %d days old, which is >= %.2d-%.2d-%d",cfg.new_days,(new_date.tm_mon + 1),new_date.tm_mday,new_date.tm_year);
  483.         strcat(io_buf,"          ");
  484.         io_buf[78] = '║';
  485.         io_buf[79] = '\0';
  486.         fprintf(list_file_p,"%s\n",io_buf);
  487.         fprintf(list_file_p,"║                                                                             ║\n");
  488.         fprintf(list_file_p,"║ %-53s%s ║\n",cfg.system_name,f_date);
  489.         fprintf(list_file_p,"╙─────────────────────────────────────────────────────────────────────────────╜\n");
  490.         fprintf(list_file_p," %-60s Fidonet 1:396/61 \n\n",VERSION);
  491.     }
  492.  
  493.     if(new_list_file_p) {
  494.         if(cfg.noibmchars) {
  495.             fprintf(new_list_file_p,"+-----------------------------------------------------------------------------+\n");
  496.             fprintf(new_list_file_p,"|         This is a list of all 'NEW' files available on this system          |\n");
  497.             fprintf(new_list_file_p,"|                                                                             |\n");
  498.             sprintf(io_buf,"|             Files are < than %d days old, which is >= %.2d-%.2d-%d",cfg.new_days,(new_date.tm_mon + 1),new_date.tm_mday,new_date.tm_year);
  499.             strcat(io_buf,"               ");
  500.             io_buf[78] = '|';
  501.             io_buf[79] = '\0';
  502.             fprintf(new_list_file_p,"%s\n",io_buf);
  503.             fprintf(new_list_file_p,"|                                                                             |\n");
  504.             fprintf(new_list_file_p,"| %-53s%s |\n",cfg.system_name,f_date);
  505.             fprintf(new_list_file_p,"+-----------------------------------------------------------------------------+\n");
  506.             fprintf(new_list_file_p," %-60s Fidonet 1:396/61 \n\n",VERSION);
  507.         }
  508.         else {
  509.             fprintf(new_list_file_p,"╓─────────────────────────────────────────────────────────────────────────────╖\n");
  510.             fprintf(new_list_file_p,"║         This is a list of all 'NEW' files available on this system          ║\n");
  511.             fprintf(new_list_file_p,"║                                                                             ║\n");
  512.             sprintf(io_buf,"║             Files are < than %d days old, which is >= %.2d-%.2d-%d",cfg.new_days,(new_date.tm_mon + 1),new_date.tm_mday,new_date.tm_year);
  513.             strcat(io_buf,"               ");
  514.             io_buf[78] = '║';
  515.             io_buf[79] = '\0';
  516.             fprintf(new_list_file_p,"%s\n",io_buf);
  517.             fprintf(new_list_file_p,"║                                                                             ║\n");
  518.             fprintf(new_list_file_p,"║ %-53s%s ║\n",cfg.system_name,f_date);
  519.             fprintf(new_list_file_p,"╙─────────────────────────────────────────────────────────────────────────────╜\n");
  520.             fprintf(new_list_file_p," %-60s Fidonet 1:396/61 \n\n",VERSION);
  521.         }
  522.     }
  523.  
  524.     /* process files.bbs */
  525.  
  526.     for(i = 0 ; i < num_areas ; i++) {
  527.         printf("\n\t%.71s",area[i]->desc);
  528.         fflush(stdout);
  529.         if(cfg.noemptyareas) {
  530.             if(Check_Empty_Area(area[i]->files_bbs)) {
  531.                 printf("\nSkipping empty area....");
  532.                 continue;
  533.             }
  534.         }
  535.         area[i]->file_count = 0;
  536.         area[i]->new_file_count = 0;
  537.         area[i]->area_bytes = 0;
  538.         area[i]->new_area_bytes = 0;
  539.         if(cfg.noibmchars) {
  540.             strcpy(area_banner,"############");
  541.             if(cfg.showmaxnames && area[i]->name[0]) {
  542.                 strcat(area_banner," ");
  543.                 strcat(area_banner,area[i]->name);
  544.                 strcat(area_banner,": ");
  545.                 strcat(area_banner,area[i]->desc);
  546.                 strcat(area_banner," ");
  547.                 area_banner[77] = ' ';
  548.                 area_banner[78] = '\0';
  549.             }
  550.             else if(area[i]->desc[0]) {
  551.                 strcat(area_banner," ");
  552.                 strcat(area_banner,area[i]->desc);
  553.                 strcat(area_banner," ");
  554.                 area_banner[77] = ' ';
  555.                 area_banner[78] = '\0';
  556.             }
  557.             strcat(area_banner,"###################################################################");
  558.         }
  559.         else {
  560.             strcpy(area_banner,"▒▒▒▒▒▒▒▒▒▒▒▒");
  561.             if(cfg.showmaxnames && area[i]->name[0]) {
  562.                 strcat(area_banner," ");
  563.                 strcat(area_banner,area[i]->name);
  564.                 strcat(area_banner,": ");
  565.                 strcat(area_banner,area[i]->desc);
  566.                 strcat(area_banner," ");
  567.                 area_banner[77] = ' ';
  568.                 area_banner[78] = '\0';
  569.             }
  570.             else if(area[i]->desc[0]) {
  571.                 strcat(area_banner," ");
  572.                 strcat(area_banner,area[i]->desc);
  573.                 strcat(area_banner," ");
  574.                 area_banner[77] = ' ';
  575.                 area_banner[78] = '\0';
  576.             }
  577.             strcat(area_banner,"▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒");
  578.         }
  579.         fprintf(list_file_p,"\n%.79s\n",area_banner);
  580.         if(new_list_file_p && !cfg.noemptyareas)
  581.             fprintf(new_list_file_p,"\n%.79s\n",area_banner);
  582.         if((fp = SH_fopen(area[i]->files_bbs,"r")) == NULL) {
  583.             printf("\nError opening '%s'!  Continuing....",area[i]->files_bbs);
  584.             fflush(stdout);
  585.         }
  586.         else {
  587.             if(cfg.use_fidx) {
  588.                 _splitpath(area[i]->files_bbs,drive,dir,fname,ext);
  589.                 strcpy(ext,".DAT");
  590.                 _makepath(fdat_path,drive,dir,fname,ext);
  591.                 if((fdat_fp = SH_fopen(fdat_path,"r")) == NULL) {
  592.                     printf("\nError opening '%s'! Continuing....",fdat_path);
  593.                     fflush(stdout);
  594.                     idx_recs = 0;
  595.                 }
  596.                 else {
  597.                     fread(&f_dat,sizeof(FDAT),1,fdat_fp);
  598.                     fdat_length = f_dat.struct_len;
  599.                     _splitpath(area[i]->files_bbs,drive,dir,fname,ext);
  600.                     strcpy(ext,".IDX");
  601.                     _makepath(fidx_path,drive,dir,fname,ext);
  602.                     files_idx = LoadFIDX(fidx_path,&idx_recs);
  603.                 }
  604.             }
  605.             while(fgets(io_buf,MAXLSIZE,fp) != NULL) {
  606.                 if(io_buf[0] == '-' || io_buf[0] == ' ' || io_buf[0] == '\n') {
  607.                     if(ptr = strchr(io_buf, '\n'))
  608.                         *ptr = '\0';
  609.                     io_buf[79] = '\0';
  610.                     fprintf(list_file_p,"\n%s",io_buf);
  611.                 }
  612.                 else {
  613.                     sscanf(io_buf,"%127s",file_path2);
  614.                     _splitpath(file_path2,drive,dir,fname,ext);
  615.                     strcpy(file_path2,drive);
  616.                     strcat(file_path2,dir);
  617.                     strcpy(file_name,fname);
  618.                     strcat(file_name,ext);
  619.                     if(file_path2[0] == '\0') {
  620.                         strcpy(file_path,area[i]->path);
  621.                         strcat(file_path,file_name);
  622.                     }
  623.                     else {
  624.                         strcpy(file_path,file_path2);
  625.                         strcat(file_path,file_name);
  626.                     }
  627.                     rc = GetFileInfo(files_idx,file_path,&file_size,&file_date,cfg.use_fidx,idx_recs,fdat_fp,fdat_length);
  628.                     if(rc != 0) {
  629.                         fprintf(list_file_p,"\n%-12s (stored offline)  ",file_name);
  630.                         new = 0;
  631.                     }
  632.                     else {
  633.                         p_buffer = _itoa(file_date.year + 80,buffer,10);
  634.                         len = strlen(p_buffer);
  635.                         fprintf(list_file_p,"\n%-12s %7ld %.2d-%.2d-%c%c",file_name,file_size,file_date.month,file_date.day,buffer[len - 2],buffer[len - 1]);
  636.                         area[i]->file_count++;
  637.                         total_count++;
  638.                         area[i]->area_bytes += file_size;
  639.                         total_bytes += file_size;
  640.                         ws_file_date = ((file_date.year + 80) * 10000) + (file_date.month * 100) + file_date.day;
  641.                         new = FALSE;
  642.                         if((!cfg.ignorebaddates && ws_file_date >= ws_new_date) ||
  643.                                  (cfg.ignorebaddates && ws_file_date >= ws_new_date && ws_file_date <= ws_current_date)) {
  644.                             new = TRUE;
  645.                             fprintf(list_file_p,"* ");
  646.                             if(new_list_file_p) {
  647.                                 if(cfg.noemptyareas && area[i]->new_file_count == 0)
  648.                                     fprintf(new_list_file_p,"\n%.79s\n",area_banner);
  649.                                 fprintf(new_list_file_p,"\n%-12s %7ld %.2d-%.2d-%c%c",file_name,file_size,file_date.month,file_date.day,buffer[len - 2],buffer[len - 1]);
  650.                                 fprintf(new_list_file_p,"* ");
  651.                                 area[i]->new_file_count++;
  652.                                 total_new_count++;
  653.                                 area[i]->new_area_bytes += file_size;
  654.                                 total_new_bytes += file_size;
  655.                             }
  656.                         }
  657.                         else
  658.                             fprintf(list_file_p,"  ");
  659.                     }
  660.                     strcpy(file_desc,io_buf);
  661.                     if(fd_ptr = strchr(file_desc,' ')) {
  662.                         fd_ptr += (strspn(fd_ptr,whitespace));
  663.                         if(cfg.stripflags && (fd_ptr[0] == '/')) {
  664.                             fd_ptr = strpbrk(fd_ptr,whitespace);
  665.                             fd_ptr += (strspn(fd_ptr,whitespace));
  666.                         }
  667.                         if(ptr = strchr(fd_ptr,'\n'))
  668.                             *ptr = '\0';
  669.                         strncpy(io_buf,fd_ptr,49);
  670.                         io_buf[49] = '\0';
  671.                         if(strlen(io_buf) > 48) {
  672.                             if(ptr = strrchr(io_buf,' '))
  673.                                 *ptr = '\0';
  674.                         }
  675.                         fprintf(list_file_p,"%s",io_buf);
  676.                         if(new && new_list_file_p)
  677.                             fprintf(new_list_file_p,"%s",io_buf);
  678.                         fd_ptr += (strlen(io_buf));
  679.                         fd_ptr += (strspn(fd_ptr,whitespace));
  680.                         while(*fd_ptr != '\0') {
  681.                             strcpy(io_buf,"                                                  ");
  682.                             io_buf[31 + cfg.indent] = '\0';
  683.                             fprintf(list_file_p,"\n%s",io_buf);
  684.                             if(new && new_list_file_p)
  685.                                 fprintf(new_list_file_p,"\n%s",io_buf);
  686.                             strncpy(io_buf,fd_ptr,(49 - cfg.indent));
  687.                             io_buf[49 - cfg.indent] = '\0';
  688.                             if(strlen(io_buf) > (48 - cfg.indent)) {
  689.                                 if(ptr = strrchr(io_buf,' '))
  690.                                     *ptr = '\0';
  691.                             }
  692.                             fprintf(list_file_p,"%s",io_buf);
  693.                             if(new && new_list_file_p)
  694.                                 fprintf(new_list_file_p,"%s",io_buf);
  695.                             fd_ptr += (strlen(io_buf));
  696.                             fd_ptr += (strspn(fd_ptr,whitespace));
  697.                         }
  698.                     }
  699.                 }
  700.             }
  701.             fclose(fp);
  702.             if(fdat_fp) {
  703.                 fclose(fdat_fp);
  704.             }
  705.             if(cfg.use_fidx && idx_recs != 0) {
  706.                 for(x = idx_recs - 1; x >= 0; x--) {
  707.                     free(files_idx[x]);
  708.                 }
  709.                 free(files_idx);
  710.             }
  711.         }
  712.         fprintf(list_file_p,"\n\n  ** %d files in this area (%ld bytes)\n\n",area[i]->file_count,area[i]->area_bytes);
  713.         if(new_list_file_p && (!cfg.noemptyareas || area[i]->new_file_count > 0))
  714.             fprintf(new_list_file_p,"\n\n  ** %d new files in this area (%ld bytes)\n\n",area[i]->new_file_count,area[i]->new_area_bytes);
  715.     }
  716.  
  717.     if(cfg.showsummary) {
  718.         if(cfg.noibmchars) {
  719.             strcpy(area_banner,"############");
  720.             strcat(area_banner," SUMMARY ");
  721.             strcat(area_banner,"###################################################################");
  722.         }
  723.         else {
  724.             strcpy(area_banner,"▒▒▒▒▒▒▒▒▒▒▒▒");
  725.             strcat(area_banner," SUMMARY ");
  726.             strcat(area_banner,"▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒");
  727.         }
  728.         fprintf(list_file_p,"\n%.79s\n",area_banner);
  729.         fprintf(list_file_p,"\n%s\n", "Area Description                                                 Files   Bytes");
  730.         if(cfg.noibmchars) {
  731.             fprintf(list_file_p,"%s\n","---------------------------------------------------------------- ----- --------");
  732.         }
  733.         else {
  734.             fprintf(list_file_p,"%s\n","──────────────────────────────────────────────────────────────── ───── ────────");
  735.         }
  736.         if(new_list_file_p) {
  737.             fprintf(new_list_file_p,"\n%.79s\n",area_banner);
  738.             fprintf(new_list_file_p,"\n%s\n", "Area Description                                                 Files   Bytes");
  739.             if(cfg.noibmchars) {
  740.                 fprintf(new_list_file_p,"%s\n","---------------------------------------------------------------- ----- --------");
  741.             }
  742.             else {
  743.                 fprintf(new_list_file_p,"%s\n","──────────────────────────────────────────────────────────────── ───── ────────");
  744.             }
  745.         }
  746.         for(i = 0 ; i < num_areas ; i++) {
  747.             if(cfg.showmaxnames) {
  748.                 strcpy(buffer,area[i]->name);
  749.                 strncat(buffer,"         ",9-strlen(area[i]->name));
  750.                 strcat(buffer," : ");
  751.                 strncat(buffer,area[i]->desc,67);
  752.             }
  753.             else {
  754.                 strcpy(buffer,area[i]->desc);
  755.             }
  756.             if(!cfg.noemptyareas || area[i]->file_count > 0) {
  757.                 fprintf(list_file_p,"%-64.64s %5u %7.0fK\n",buffer,area[i]->file_count,((double)(area[i]->area_bytes)) / 1000);
  758.                 if(new_list_file_p && (!cfg.noemptyareas || area[i]->new_file_count > 0)) {
  759.                     fprintf(new_list_file_p,"%-64.64s %5u %7.0fK\n",buffer,area[i]->new_file_count,((double)(area[i]->new_area_bytes)) / 1000);
  760.                 }
  761.             }
  762.         }
  763.         if(cfg.noibmchars) {
  764.             fprintf(list_file_p,"%s\n","-------------------------------------------------------------------------------");
  765.         }
  766.         else {
  767.             fprintf(list_file_p,"%s\n","───────────────────────────────────────────────────────────────────────────────");
  768.         }
  769.         if(new_list_file_p) {
  770.             if(cfg.noibmchars) {
  771.                 fprintf(new_list_file_p,"%s\n","-------------------------------------------------------------------------------");
  772.             }
  773.             else {
  774.                 fprintf(new_list_file_p,"%s\n","───────────────────────────────────────────────────────────────────────────────");
  775.             }
  776.         }
  777.     }
  778.  
  779.     /* finish things up */
  780.  
  781.     if(cfg.noibmchars) {
  782.         fprintf(list_file_p,"\n %-55s%s\n",cfg.system_name,f_date);
  783.         fprintf(list_file_p,"+-----------------------------------------------------------------------------+\n");
  784.         sprintf(io_buf,"| There are a total of %d files on this system (%ld bytes)",total_count,total_bytes);
  785.         strcat(io_buf,"                               ");
  786.         io_buf[78] = '|';
  787.         io_buf[79] = '\0';
  788.         fprintf(list_file_p,"%s\n",io_buf);
  789.         fprintf(list_file_p,"|                                                                             |\n");
  790.         fprintf(list_file_p,"| %-58s Fidonet 1:396/61 |\n",VERSION);
  791.         fprintf(list_file_p,"+-----------------------------------------------------------------------------+\n");
  792.     }
  793.     else {
  794.         fprintf(list_file_p,"\n %-55s%s\n",cfg.system_name,f_date);
  795.         fprintf(list_file_p,"╓─────────────────────────────────────────────────────────────────────────────╖\n");
  796.         sprintf(io_buf,"║ There are a total of %d files on this system (%ld bytes)",total_count,total_bytes);
  797.         strcat(io_buf,"                               ");
  798.         io_buf[78] = '║';
  799.         io_buf[79] = '\0';
  800.         fprintf(list_file_p,"%s\n",io_buf);
  801.         fprintf(list_file_p,"║                                                                             ║\n");
  802.         fprintf(list_file_p,"║ %-58s Fidonet 1:396/61 ║\n",VERSION);
  803.         fprintf(list_file_p,"╙─────────────────────────────────────────────────────────────────────────────╜\n");
  804.     }
  805.     fclose(list_file_p);
  806.     if(remove(cfg.list_file) != 0 && errno == EACCESS)
  807.         printf("\n\nError deleting old FileList '%s'!",cfg.list_file);
  808.     if(rename(temp_fl,cfg.list_file) != 0)
  809.         printf("\n\nError renaming '%s' to '%s'!",temp_fl,cfg.list_file);
  810.  
  811.     if(new_list_file_p) {
  812.         if(cfg.noibmchars) {
  813.             fprintf(new_list_file_p,"\n %-55s%s\n",cfg.system_name,f_date);
  814.             fprintf(new_list_file_p,"+-----------------------------------------------------------------------------+\n");
  815.             sprintf(io_buf,"| There are a total of %d new files on this system (%ld bytes)",total_new_count,total_new_bytes);
  816.             strcat(io_buf,"                               ");
  817.             io_buf[78] = '|';
  818.             io_buf[79] = '\0';
  819.             fprintf(new_list_file_p,"%s\n",io_buf);
  820.             fprintf(new_list_file_p,"|                                                                             |\n");
  821.             fprintf(new_list_file_p,"| %-58s Fidonet 1:396/61 |\n",VERSION);
  822.             fprintf(new_list_file_p,"+-----------------------------------------------------------------------------+\n");
  823.         }
  824.         else {
  825.             fprintf(new_list_file_p,"\n %-55s%s\n",cfg.system_name,f_date);
  826.             fprintf(new_list_file_p,"╓─────────────────────────────────────────────────────────────────────────────╖\n");
  827.             sprintf(io_buf,"║ There are a total of %d new files on this system (%ld bytes)",total_new_count,total_new_bytes);
  828.             strcat(io_buf,"                               ");
  829.             io_buf[78] = '║';
  830.             io_buf[79] = '\0';
  831.             fprintf(new_list_file_p,"%s\n",io_buf);
  832.             fprintf(new_list_file_p,"║                                                                             ║\n");
  833.             fprintf(new_list_file_p,"║ %-58s Fidonet 1:396/61 ║\n",VERSION);
  834.             fprintf(new_list_file_p,"╙─────────────────────────────────────────────────────────────────────────────╜\n");
  835.         }
  836.         fclose(new_list_file_p);
  837.         if(remove(cfg.new_list_file) != 0 && errno == EACCESS)
  838.             printf("\n\nError deleting old NewFileList '%s'!",cfg.new_list_file);
  839.         if(rename(temp_nfl,cfg.new_list_file) != 0)
  840.             printf("\n\nError renaming '%s' to '%s'!",temp_nfl,cfg.new_list_file);
  841.     }
  842.     printf("\n\n....Done!\n");
  843. }
  844.  
  845. int Check_Exclude(char *key, char **list, int num)
  846. {
  847.     int i = 0;
  848.     char found = FALSE;
  849.  
  850.     while(i < num && !found) {
  851.         if(strcmp(key,list[i]) == 0) {
  852.             found = TRUE;
  853.         }
  854.         i++;
  855.     }
  856.     return(found);
  857. }
  858.  
  859. int Check_Empty_Area(char *file_path)
  860. {
  861.     FILE *fp;
  862.     char io_buf[MAXLSIZE];
  863.  
  864.     if((fp = SH_fopen(file_path,"r")) == NULL) {
  865.         printf("\nError opening '%s'!  Continuing....",file_path);
  866.         fflush(stdout);
  867.         return(1);
  868.     }
  869.     else {
  870.         while(fgets(io_buf,MAXLSIZE,fp) != NULL) {
  871.             if(io_buf[0] != '-' && io_buf[0] != ' ' && io_buf[0] != '\n') {
  872.                 fclose(fp);
  873.                 return(0);
  874.             }
  875.         }
  876.         fclose(fp);
  877.         return(1);
  878.     }
  879. }
  880.  
  881. char *Get_Arg(char *string)
  882. {
  883.     char *ptr;
  884.  
  885.     ptr = string + strcspn(string,whitespace);
  886.     ptr += strspn(ptr,whitespace);
  887.     return(ptr);
  888. }
  889.  
  890. int GetFileInfo(FIDX **f_idx, char *file_name, ULONG *file_size, FDATE *file_date, char use_fidx, unsigned idx_recs, FILE *fdat_fp, int fdat_length)
  891. {
  892.     ULONG PathInfoLevel = 1;
  893.     FILESTATUS3 PathInfoBuf;
  894.     APIRET rc;
  895.     unsigned f_idx_rec;
  896.     char drive[3];
  897.     char dir[66];
  898.     char fname[9];
  899.     char ext[5];
  900.     char key[13];
  901.     FDAT f_dat;
  902.  
  903.     if(use_fidx && idx_recs != 0 && fdat_fp != NULL) {
  904.         _splitpath(file_name,drive,dir,fname,ext);
  905.         strcpy(key,fname);
  906.         strcat(key,ext);
  907.         f_idx_rec = SearchFIDX(f_idx,idx_recs,key);
  908.         if(f_idx_rec != -1) {
  909.             fseek(fdat_fp,f_idx[f_idx_rec]->fpos * (long)fdat_length,SEEK_SET);
  910.             if(fread(&f_dat,sizeof(FDAT),1,fdat_fp)) {
  911.                 if(f_dat.fsize == 0 && f_dat.udate.msg_st.date.da == 0 && f_dat.udate.msg_st.date.mo == 0 && f_dat.udate.msg_st.date.yr == 0) {
  912.                     return(1);
  913.                 }
  914.                 else {
  915.                     *file_size = f_dat.fsize;
  916.                     file_date->day = f_dat.udate.msg_st.date.da;
  917.                     file_date->month = f_dat.udate.msg_st.date.mo;
  918.                     file_date->year = f_dat.udate.msg_st.date.yr;
  919.                     return(0);
  920.                 }
  921.             }
  922.         }
  923.     }
  924.  
  925.     rc = DosQueryPathInfo(file_name,PathInfoLevel,&PathInfoBuf,sizeof(FILESTATUS3));
  926.     if(rc == 0) {
  927.         *file_size = PathInfoBuf.cbFile;
  928.         *file_date = PathInfoBuf.fdateLastWrite;
  929.         return(0);
  930.     }
  931.     else {
  932.         return(1);
  933.     }
  934. }
  935.  
  936. FIDX **LoadFIDX(char *file_path, unsigned *num_recs)
  937. {
  938.     unsigned ws_recs;
  939.     ULONG PathInfoLevel = 1;
  940.     FILESTATUS3 PathInfoBuf;
  941.     APIRET rc;
  942.     int i;
  943.     int x;
  944.     FILE *fidx_fp;
  945.     FIDX **f_idx;
  946.     FIDX fidx_rec;
  947.  
  948.     if((fidx_fp = SH_fopen(file_path,"rb")) == NULL) {
  949.         printf("\nError opening '%s'!  Continuing....",file_path);
  950.         *num_recs = 0;
  951.         return(NULL);
  952.     }
  953.     if((f_idx = malloc(sizeof(FIDX *))) == NULL) {
  954.         printf("\nNot enough memory to load FILES.IDX!  Exiting....");
  955.         exit(255);
  956.     }
  957.     for(i=0; fread(&fidx_rec,sizeof(FIDX),1,fidx_fp); i++) {
  958.         if((f_idx[i] = malloc(sizeof(FIDX))) == NULL) {
  959.             printf("\nNot enough memory to load FILES.IDX!  Exiting....");
  960.             exit(255);
  961.         }
  962.         strncpy(f_idx[i]->name,fidx_rec.name,MAX_FN_LEN);
  963.         f_idx[i]->anum = fidx_rec.anum;
  964.         f_idx[i]->fpos = fidx_rec.fpos;
  965.         if((f_idx = realloc(f_idx,((i + 2) * sizeof(FIDX *)))) == NULL) {
  966.             printf("\nNot enough memory to load FILES.IDX!  Exiting....");
  967.             exit(255);
  968.         }
  969.     }
  970.     fclose(fidx_fp);
  971.     *num_recs = i;
  972.     strsort(f_idx, *num_recs);
  973.     return(f_idx);
  974. }
  975.  
  976. unsigned SearchFIDX(FIDX **f_idx, int num_recs, char *key)
  977. {
  978.     unsigned low;
  979.     unsigned high;
  980.     unsigned median;
  981.  
  982.     low = 0;
  983.     high = num_recs - 1;
  984.  
  985.     do {
  986.         median = (low + high) / 2;
  987.         if(strnicmp(key,f_idx[median]->name,MAX_FN_LEN) < 0) {
  988.             high = median - 1;
  989.         }
  990.         else {
  991.             low = median + 1;
  992.         }
  993.     } while(!(strnicmp(key,f_idx[median]->name,MAX_FN_LEN) == 0 || low > high));
  994.     if(strnicmp(key,f_idx[median]->name,MAX_FN_LEN) == 0) {
  995.         return(median);
  996.     }
  997.     else {
  998.         return(-1);
  999.     }
  1000. }
  1001.  
  1002. /*
  1003. **  strsort() -- Shell sort an array of string pointers via strcmp()
  1004. **  public domain by Ray Gardner   Denver, CO   12/88
  1005. */
  1006.  
  1007. void strsort (FIDX **array, size_t array_size)
  1008. {
  1009.       size_t gap, i, j;
  1010.       FIDX **a, **b, *tmp;
  1011.  
  1012.       for (gap = 0; ++gap < array_size; )
  1013.             gap *= 2;
  1014.       while (gap /= 2)
  1015.       {
  1016.             for (i = gap; i < array_size; i++)
  1017.             {
  1018.                   for (j = i - gap; ;j -= gap)
  1019.                   {
  1020.                         a = array + j;
  1021.                         b = a + gap;
  1022.                         if (strnicmp((*a)->name, (*b)->name, MAX_FN_LEN) <= 0)
  1023.                               break;
  1024.                         tmp = *a;
  1025.                         *a = *b;
  1026.                         *b = tmp;
  1027.                         if (j < gap)
  1028.                               break;
  1029.                   }
  1030.             }
  1031.       }
  1032. }
  1033.  
  1034. FILE *SH_fopen(char *filename, char *mode)
  1035. {
  1036.     HFILE file_handle;
  1037.     ULONG action_taken;
  1038.     APIRET rc;
  1039.     FILE *fp;
  1040.  
  1041.     rc = DosOpen(filename,&file_handle,&action_taken,0L,FILE_NORMAL,
  1042.                  FILE_OPEN | OPEN_ACTION_FAIL_IF_NEW,
  1043.                  OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY,0L);
  1044.     if(rc != 0) {
  1045.         return(NULL);
  1046.     }
  1047.     else {
  1048.         if((fp = fdopen(file_handle,mode)) == NULL) {
  1049.             DosClose(file_handle);
  1050.             return(NULL);
  1051.         }
  1052.         else {
  1053.             return(fp);
  1054.         }
  1055.     }
  1056. }
  1057.