home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / OS2 / DWNSRT47.ZIP / DOWNSRV.C < prev   
Encoding:
C/C++ Source or Header  |  1990-12-01  |  19.0 KB  |  561 lines

  1. /* ============================================================= */
  2. /*  Rob Hamerling's MAXIMUS download file scan and sort utility. */
  3. /*  -> Collection of general service routines for DOWNSORT.      */
  4. /* ============================================================= */
  5.  
  6. // #define DEBUG_MODE
  7.  
  8. #define INCL_BASE
  9. #include <os2.h>
  10.  
  11. #include "downsort.h"
  12.  
  13. #include "ctype.h"
  14. #include "stdio.h"
  15. #include "stdlib.h"
  16. #include "string.h"
  17. #include "time.h"
  18.  
  19. /* ------------------- */
  20. /* Welcome to the user */
  21. /* ------------------- */
  22. void show_welcome()
  23. {
  24.   printf("\n%15s╔%22.22s╗", "",HD);
  25.   printf("\n╔%14.14s╣ %8.8s version %d.%d%c╠%15.15s╗",
  26.                     HD,PROGNAME,VERSION,SUBVERS,SUFFIX,HD);
  27.   printf("\n║  Copyright   ╚%22.22s╝   Shareware   ║", HD);
  28.   printf("\n║  %s %-38.38s║", MAX,PROGDESC);
  29.   printf("\n║      by %-13.13s, %-29s║", AUTHOR,CITY);
  30.   printf("\n║%-26s%27s║", PHONE,FIDO);
  31.   printf("\n╚%26.26s%27.27s╝\n", HD,HD);
  32.   }
  33.  
  34. /* ======================================================== */
  35. /* Compare two filenames, first call should be with x==0    */
  36. /* First name must be regular "8.3" format filename.        */
  37. /* Second name may contain wildcards, but the compare will  */
  38. /* be against the saved first name when x!=0.               */
  39. /* ======================================================== */
  40. int wild_comp(x,a,b)
  41. char a[],b[];                           // file spec strings
  42. int  x;                                 // x==0 first compare
  43.                                         // x!=0 subsequent compare
  44. {
  45.   int i;
  46.   static char na[11],nb[11];            // formatted filename fields
  47.                                         // keep 'm for subsequent calls
  48.   static char empty_ext[]  = "";     // for compare files without ext.
  49.  
  50.   i = non_wild_init(8,na,a);            // init non-wild string
  51.   switch(a[i]) {                        // after fileNAME
  52.     case ' ' :
  53.     case '\0':
  54.       i = non_wild_init(3,na+8,empty_ext);  // empty extension
  55.       break;
  56.     case '.' :
  57.       i = non_wild_init(3,na+8,a+i+1);  // process extension
  58.       break;
  59.     default:                            // invalid filename
  60.       break;
  61.     }
  62.  
  63.   if (x==0) {                           // first compare with 2nd name
  64.     i = wild_init(8,nb,b);
  65.     switch(b[i]) {
  66.       case ' ' :
  67.       case '\0':
  68.         i = wild_init(3,nb+8,empty_ext);  // empty extension
  69.         break;
  70.       case '.' :
  71.         i = wild_init(3,nb+8,b+i+1);    // process extension
  72.         break;
  73.       default:
  74.         break;
  75.       }
  76.     }
  77. #if defined(DEBUG_MODE)
  78.   printf("\n");                         // debug of wild compare
  79.   for (i=0; i<11; ++i)
  80.     printf("%c",(na[i]!='\0')?na[i]:' ');
  81.   printf(" ");
  82.   for (i=0; i<11; ++i)
  83.     printf("%02X",na[i]);
  84.   printf("   ");
  85.   for (i=0; i<11; ++i)
  86.     printf("%c",(nb[i]!='\0')?nb[i]:' ');
  87.   printf(" ");
  88.   for (i=0; i<11; ++i)
  89.     printf("%02X",nb[i]);
  90. #endif
  91.  
  92.   for (i=0; i<11 && (na[i]==nb[i] || na[i]=='\0' || nb[i]=='\0'); i++);
  93.  
  94.   if (i>=11)                             // strings equal
  95.     return(0);
  96.   else
  97.     return(na[i]-nb[i]);                 //
  98.   }
  99.  
  100. /* =========================================== */
  101. /* Init string for wild-card filenames compare */
  102. /* =========================================== */
  103. int wild_init(n,p,q)
  104. int  n;                                 // max length of strings
  105. char p[],q[];                           // p is destination (length n)
  106.                                         // q is source (MAX length n)
  107. {
  108.   int i,j;
  109.  
  110.   i=j=0;
  111.   while (i<n) {                         // process string 'q'
  112.     switch(q[j]) {
  113.       case '?':                         // single wild char
  114.         p[i++] = '\0';                  // matches with any other char
  115.         j++;                            // proceed with next char
  116.         break;
  117.       case '.':                         // end of filespec-part
  118.       case ' ':                         // logical end of string
  119.       case '\0':                        // end of string
  120.         while (i<n)                     // fill
  121.           p[i++] = '';                 // insert filler chars
  122.         break;
  123.       case '*':                         // wild string
  124.         while (i<n)                     // fill
  125.           p[i++] = '\0';                // matches with any other char
  126.         j++;                            // to next char
  127.         break;
  128.       default:                          // 'normal' characters
  129.         p[i] = toupper(q[i]);           // copy in UPPERcase
  130.         i++; j++;                       // proceed with next char
  131.         break;
  132.       }
  133.     }
  134.  
  135.   return(j);                            // displ. of last examined char
  136.   }
  137.  
  138. /* ==================================================== */
  139. /* Init string for non-wild-card filenames compare      */
  140. /* No wild-cards expected, no trasnlation to upper case */
  141. /* ==================================================== */
  142. int non_wild_init(n,p,q)
  143. int  n;                                 // max length of strings
  144. char p[],q[];                           // p is destination (length n)
  145.                                         // q is source (MAX length n)
  146. {
  147.   int i,j;
  148.  
  149.   i=j=0;
  150.   while (i<n) {                         // process string 'q'
  151.     if (q[j]=='.' || q[j]==' ' || q[j]=='\0') {
  152.       p[i] = '';                       // insert filler char
  153.       i++;                              // rest zeroes (no j-increment!)
  154.       }
  155.     else {
  156.       p[i] = toupper(q[i]);             // copy in UPPER case
  157.       i++; j++;                         // proceed with next char
  158.       }
  159.     }
  160.  
  161.   return(j);                            // displ. of last examined char
  162.   }
  163.  
  164. /* ----------------------------------------------- */
  165. /* Transform file-date into 10-char string         */
  166. /* COUNTRY format mm-dd-yy (USA) or dd-mm-jj (EUR) */
  167. /* ----------------------------------------------- */
  168. char *f_date(dat)
  169. struct _FDATE dat;
  170. {
  171.   static char date[10] = {'\0'};        // work buffer
  172.   sprintf(date,"%2u%s%02u%s%02u%c",
  173.          ((c_info.fsDateFmt == 0) ? dat.month : dat.day),
  174.            c_info.szDateSeparator,
  175.          ((c_info.fsDateFmt == 0) ? dat.day : dat.month),
  176.            c_info.szDateSeparator,
  177.          (dat.year+80)%100,             /* allow 2 digits! */
  178.           '\0');
  179.   return(date);
  180.   }
  181.  
  182. /* -------------------------------------------------------------- */
  183. /* Transform file-time into string (hh:mm:ssa)                    */
  184. /* COUNTRY format hh:mm:ssa (12 hr USA) or hh-mm-ss  (24 hr EUR)  */
  185. /* -------------------------------------------------------------- */
  186. char *f_time(tim)
  187. struct _FTIME tim;
  188. {
  189.   static char time[10] = {'\0'};        // work buffer
  190.   sprintf(time,"%2u%s%02u%s%02u%s%c",
  191.           (c_info.fsTimeFmt==0 && tim.hours>12) ? tim.hours-12 : tim.hours,
  192.            c_info.szTimeSeparator,
  193.           tim.minutes,
  194.            c_info.szTimeSeparator,
  195.           tim.twosecs*2,
  196.           ((c_info.fsTimeFmt==0) ? ((tim.hours>11) ? "p" : "a") : " "),
  197.           '\0');
  198.   return(time);
  199.   }
  200.  
  201. /* ====================================================== */
  202. /* Compare for sort on file-date/time + filename + area   */
  203. /* ====================================================== */
  204. int sort_new(p,q)
  205. struct _filechain **p,**q;
  206. {
  207.   int    rc;
  208.   ULONG  ad,bd,td;
  209.   struct _filechain *a,*b;
  210.  
  211.   a = *p;
  212.   b = *q;
  213.  
  214.   ad = file_time(a->wdate,a->wtime);
  215.   td = file_time(a->cdate,a->ctime);
  216.   if (ad < td)                          // take latest date
  217.     ad = td;
  218.  
  219.   bd = file_time(b->wdate,b->wtime);
  220.   td = file_time(b->cdate,b->ctime);
  221.   if (bd < td)                          // take latest date
  222.     bd = td;
  223.  
  224.   if (bd==ad) {                         // equal timestamps
  225.     rc = strcmp(a->fname,b->fname);
  226.     if (rc)                             // unequal filenames
  227.       return(rc);
  228.     else
  229.       return(strcmp(a->parea->name,b->parea->name));  // area-code
  230.     }
  231.   else
  232.     return((bd<ad) ? -1 : +1);
  233.   }
  234.  
  235. /* ========================================= */
  236. /* Compare for sort on filename + area-code  */
  237. /* ========================================= */
  238. int sort_gbl(p,q)
  239. struct _filechain **p,**q;
  240. {
  241.   int rc;
  242.   struct _filechain *a,*b;
  243.  
  244.   a = *p;
  245.   b = *q;
  246.   rc = strcmp(a->fname,b->fname);
  247.   if (rc)                               // unequal filename
  248.     return(rc);
  249.   else
  250.     return(strcmp(a->parea->name,b->parea->name));    // area-code
  251.   }
  252.  
  253. /* ========================================= */
  254. /* Compare for sort on area code + filename  */
  255. /* ========================================= */
  256. int sort_all(p,q)
  257. struct _filechain **p,**q;
  258. {
  259.   int rc;
  260.   struct _filechain *a,*b;
  261.  
  262.   a = *p;
  263.   b = *q;
  264.   rc = strcmp(a->parea->name,b->parea->name);
  265.   if (rc)                               // unequal areacode
  266.     return(rc);
  267.   else
  268.     return(strcmp(a->fname,b->fname));  // filename
  269.   }
  270.  
  271. /* ====================================================== */
  272. /* Compare for sort on area + file-date/time + filename   */
  273. /* ====================================================== */
  274. int sort_al2(p,q)
  275. struct _filechain **p,**q;
  276. {
  277.   int    rc;
  278.   ULONG  ad,bd,td;
  279.   struct _filechain *a,*b;
  280.  
  281.   a = *p;
  282.   b = *q;
  283.   rc = strcmp(a->parea->name,b->parea->name);
  284.   if (rc)                               // unequal area-name
  285.     return(rc);
  286.   else {
  287.     ad = file_time(a->wdate,a->wtime);
  288.     td = file_time(a->cdate,a->ctime);
  289.     if (ad < td)                        // take latest date
  290.       ad = td;
  291.     bd = file_time(b->wdate,b->wtime);
  292.     td = file_time(b->cdate,b->ctime);
  293.     if (bd < td)                        // take latest date
  294.       bd = td;
  295.     if (bd!=ad)                         // unequal date
  296.       return((bd<ad) ? -1 : +1);
  297.     else
  298.       return(strcmp(a->fname,b->fname));  // filename
  299.     }
  300.   }
  301.  
  302. /* ==================================================== */
  303. /* Compare for sort on area code + privilege + filename */
  304. /* No sort on privilege if below area-privilege.        */
  305. /* ==================================================== */
  306. int sort_fil(p,q)
  307. struct _filechain **p,**q;
  308. {
  309.   int rc;
  310.   struct _filechain *a,*b;
  311.  
  312.   a = *p;
  313.   b = *q;
  314.   rc = strcmp(a->parea->name,b->parea->name);
  315.   if (rc)                               // unequal areacode
  316.     return(rc);
  317.   else {
  318.     if (a->priv <= a->parea->priv &&    // both within area priv
  319.         b->priv <= b->parea->priv)
  320.       return(strcmp(a->fname,b->fname));  // sort on filename
  321.     else if (a->priv == b->priv)        // same privilege
  322.       return(strcmp(a->fname,b->fname));  // filename
  323.     else
  324.       return (a->priv - b->priv);       // file priv
  325.     }
  326.   }
  327.  
  328. /* ========================================== */
  329. /* Compare for sort on area code of AREA-info*/
  330. /* ========================================== */
  331. int sort_summ(p,q)
  332. struct _downpath *p,*q;
  333. {
  334.   return(strcmp(p->name,q->name));
  335.   }
  336.  
  337. /* ---------------------------- */
  338. /* Sort file-info pointer array */
  339. /* ---------------------------- */
  340. void    psort(arr, left, right, comp)
  341. struct  _filechain **arr;               // pointer to array
  342. int     left,right;                     // left and right boundaries
  343. int     (*comp)();                      // ptr to compare function
  344. {
  345.   int    asc,desc;
  346.   struct _filechain *ref,*tmp;
  347.  
  348.   if ((right-left) < 1)                 // too few elements
  349.     return;
  350.  
  351.   asc   = left;                         // left 'wall'
  352.   desc  = right;                        // right 'wall'
  353.   ref  = arr[(left + right)/2];         // reference value
  354.  
  355.   do {
  356.     while (comp(&arr[asc],&ref) < 0)  // move right
  357.       asc++;
  358.     while (comp(&arr[desc],&ref) > 0) // move left
  359.       desc--;
  360.     if (asc <= desc) {                   // swap
  361.       tmp = arr[desc];
  362.       arr[desc--] = arr[asc];
  363.       arr[asc++] = tmp;
  364.       }
  365.     } while (asc <= desc);
  366.  
  367.   if ((desc-left) < (right-asc)) {      // sort smaller part first
  368.     if (left < desc)
  369.       psort(arr, left, desc, comp);
  370.     if (right > asc)
  371.       psort(arr, asc, right, comp);
  372.     }
  373.   else {
  374.     if (right > asc)
  375.       psort(arr, asc, right, comp);
  376.     if (left < desc)
  377.       psort(arr, left, desc, comp);
  378.     }
  379.   }
  380.  
  381. /* =================== */
  382. /* determine file-age  */
  383. /* =================== */
  384. char  file_age_ind(fd,ft)
  385. struct _FDATE fd;
  386. struct _FTIME ft;
  387. {
  388.   int  age;
  389.  
  390.   age = (int)((time(NULL) - file_time(fd,ft))/86400);  // days
  391.   if (age>30)
  392.     return(' ');                        // older than a month
  393.   else {
  394.     if (age>7)                          // older than 7 days
  395.       return(DAYS_30);
  396.     else {
  397.       if (age>=0)                       // non-negative negative age
  398.         return(DAYS_7);                 // a week
  399.       else
  400.         return('-');                    // negative age
  401.       }
  402.     }
  403.   }
  404.  
  405. /* ============================================ */
  406. /* Compare for newest acquisition in ALL-list   */
  407. /* ============================================ */
  408. struct _filechain *new_acq(a,b)
  409. struct _filechain *a,*b;
  410. {
  411.   long ad,bd,td;
  412.  
  413.   if (b==NULL)                          // right might be not assigned
  414.     return(a);                          // then return first
  415.   ad = file_time(a->wdate,a->wtime);
  416.   td = file_time(a->cdate,a->ctime);
  417.   if (ad < td)                          // take latest date
  418.     ad = td;
  419.   bd = file_time(b->wdate,b->wtime);
  420.   td = file_time(b->cdate,b->ctime);
  421.   if (bd < td)                          // take latest date
  422.     bd = td;
  423.   if (ad==bd)                           // equal dates
  424.     return(b);                          // (either)
  425.   else
  426.     return((ad>bd) ? a : b);            // return most recent
  427.   }
  428.  
  429. /* ============================================================== */
  430. /* reformat file-date into long time-value like C time convention */
  431. /* ============================================================== */
  432. long  file_time(fd,ft)
  433. struct _FDATE fd;                     // file date
  434. struct _FTIME ft;                     // file time
  435. {
  436.   static int mon_tab[] = {0,31,59,90,120,151,181,212,243,273,304,334};
  437.                                       // ignore leapyear February!
  438.   return((((fd.year+10)*1461+1)/4 +
  439.            mon_tab[fd.month-1] +
  440.            fd.day - 1) * 86400L +
  441.           ft.hours * 3600 +
  442.           ft.minutes * 60 +
  443.           ft.twosecs * 2);
  444.   }
  445.  
  446. /* ============================================================== */
  447. /* routine to select a substring while skipping leading blanks    */
  448. /*         and ending within the boundaries on a word-end.        */
  449. /*         Truncate if single word. Respect NL as end of string.  */
  450. /*         Return strlen,  0 for NULL-pointer.                    */
  451. /* ============================================================== */
  452. int strsubw(a,b,m)
  453. char *a,**b;                            // in-string, start-substring
  454. int  m;                                 // max substring length
  455. {
  456.   int i,j,k;                            // counters
  457.  
  458.   if (a==NULL)                          // NULL pointer
  459.     return(0);                          // no string
  460.  
  461.   for (i=0; a[i] == ' '; ++i);          // skip leading blanks
  462.   a = *b = a+i;                         // offset to first non-blank char
  463.   for (i=0; a[i] != '\0' && a[i]!='\n'; ++i); // search end string
  464.   if (i==0)                             // nothing left
  465.     return(0);                          // end!
  466.  
  467.   for (k=0; k<m && k<i; ++k);           // maximum substring
  468.   if (k<i) {                            // there is more in string
  469.     if (a[k]==' ' || a[k]=='\n' || a[k]=='\0');  // word boundary
  470.     else {
  471.       for (j=k-1; j>0 && a[j]!=' '; --j); // try to remove 'split' word
  472.       if (j>0)                          // any space found?
  473.         k = j;                          // OK, else split!
  474.       }
  475.     }
  476.   for (; k>0 && a[k-1] == ' '; --k);    // remove trailing blanks
  477.   return(k);                            // return length of substring
  478.                                         // b contains start-point
  479.   }
  480.  
  481. /* ====================================================== */
  482. /* Function to locate next non-blank character in buffer. */
  483. /* Returns pointer to word or NULL-ptr if no next word.   */
  484. /* ====================================================== */
  485. char *next_word(line)
  486. char *line;                             //
  487. {
  488.   unsigned int i;
  489.  
  490.   for (i=0; line[i]!=' '  &&            // skip non-blanks
  491.             line[i]!='\n' &&
  492.             line[i]!='\0'; ++i);
  493.   for (   ; line[i]==' '; ++i);         // skip blanks
  494.   if (line[i] != '\0' &&
  495.       line[i] != '\n')
  496.     return(line+i);                     // next word found
  497.   else
  498.     return(NULL);                       // NULL if no next word
  499.   }
  500.  
  501. /* =========================================== */
  502. /* Function to make ASCIIZ string of ONE word. */
  503. /* =========================================== */
  504. char *asciiz(buf)
  505. char *buf;
  506. {
  507.   unsigned int i;
  508.   static char buf2[255];                // return buffer
  509.  
  510.   for (i=0; buf[i] != ' '  &&           // end copy at first blank
  511.             buf[i] !='\n'  &&           // or end of line
  512.             buf[i] !='\0'; ++i)         // or end of string
  513.     buf2[i] = buf[i];                   // copy
  514.   buf2[i] = '\0';                       // end of string
  515.   return(buf2);                         // pointer to ASCIIZ string
  516.   }
  517.  
  518. /* ================================== */
  519. /* some marketing below every report! */
  520. /* ================================== */
  521. void signature(pf,now)
  522. FILE *pf;                               // file pointer
  523. char *now;                              // timestamp string
  524. {
  525.   static char *mode[] = {"DOS","OS/2"};
  526.  
  527.   fprintf(pf,"\n\n %-.40s%-.28s",HD,HD);
  528.   fprintf(pf,"\n  %s %d.%d%c by %s, on %s under %s %d.%d ",
  529.                 PROGNAME,VERSION,SUBVERS,SUFFIX,AUTHOR,now,
  530.                 mode[_osmode & 1],
  531.                 _osmajor/((_osmode)?10:1),
  532.                 _osminor/10);
  533.   fprintf(pf,"\n %-.40s%-.28s\n",HD,HD);
  534.   }
  535.  
  536. /* ================ */
  537. /* HELP information */
  538. /* ================ */
  539. void show_help()
  540. {
  541.   printf("\nSyntax:  DOWNSORT  [commandline-parameters]\n");
  542.   printf("\n@filespec   - Filespec of Configuration file with processing parameters");
  543.   printf("\nBBS[:p]     - Make BBS-list    ╗");
  544.   printf("\nNEW[:pp]    - Make NEW-list(s) ╠═ for 1 or more privilege levels");
  545.   printf("\nALL[:pp]    - Make ALL-list(s) ║");
  546.   printf("\nGBL[:pp]    - Make GBL-list(s) ╝");
  547.   printf("\nFIL[:fpath] - (Re-)create FILES.BBS files");
  548.   printf("\n-T|W        - All long file descriptions to be Truncated or Wrapped");
  549.   printf("\n-A|D        - Files to be sorted Alphabetically or on Date");
  550.   printf("\n-H|Q|V      - Display this HELP-screen, or run Quietly or Verbose");
  551.   printf("\n");
  552.   printf("\n - p     : first letter of privilege (i.e. D=Disgrace, N=Normal, etc).");
  553.   printf("\n - pp    : list generated for each specified privilege.");
  554.   printf("\n - fpath : output directory of FILES.BBS files.");
  555.   printf("\n\nThese parameters override program and configurationfile values.");
  556.   printf("\nRead documentation or sample configuration file "
  557.             "for details and defaults.\n");
  558.   exit(1);
  559.   }
  560.  
  561.