home *** CD-ROM | disk | FTP | other *** search
- /* ============================================================= */
- /* Rob Hamerling's MAXIMUS download file scan and sort utility. */
- /* -> Collection of general service routines for DOWNSORT. */
- /* ============================================================= */
-
- // #define DEBUG_MODE
-
- #define INCL_BASE
- #include <os2.h>
-
- #include "downsort.h"
-
- #include "ctype.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "string.h"
- #include "time.h"
-
- /* ------------------- */
- /* Welcome to the user */
- /* ------------------- */
- void show_welcome()
- {
- printf("\n%15s╔%22.22s╗", "",HD);
- printf("\n╔%14.14s╣ %8.8s version %d.%d%c╠%15.15s╗",
- HD,PROGNAME,VERSION,SUBVERS,SUFFIX,HD);
- printf("\n║ Copyright ╚%22.22s╝ Shareware ║", HD);
- printf("\n║ %s %-38.38s║", MAX,PROGDESC);
- printf("\n║ by %-13.13s, %-29s║", AUTHOR,CITY);
- printf("\n║%-26s%27s║", PHONE,FIDO);
- printf("\n╚%26.26s%27.27s╝\n", HD,HD);
- }
-
- /* ======================================================== */
- /* Compare two filenames, first call should be with x==0 */
- /* First name must be regular "8.3" format filename. */
- /* Second name may contain wildcards, but the compare will */
- /* be against the saved first name when x!=0. */
- /* ======================================================== */
- int wild_comp(x,a,b)
- char a[],b[]; // file spec strings
- int x; // x==0 first compare
- // x!=0 subsequent compare
- {
- int i;
- static char na[11],nb[11]; // formatted filename fields
- // keep 'm for subsequent calls
- static char empty_ext[] = ""; // for compare files without ext.
-
- i = non_wild_init(8,na,a); // init non-wild string
- switch(a[i]) { // after fileNAME
- case ' ' :
- case '\0':
- i = non_wild_init(3,na+8,empty_ext); // empty extension
- break;
- case '.' :
- i = non_wild_init(3,na+8,a+i+1); // process extension
- break;
- default: // invalid filename
- break;
- }
-
- if (x==0) { // first compare with 2nd name
- i = wild_init(8,nb,b);
- switch(b[i]) {
- case ' ' :
- case '\0':
- i = wild_init(3,nb+8,empty_ext); // empty extension
- break;
- case '.' :
- i = wild_init(3,nb+8,b+i+1); // process extension
- break;
- default:
- break;
- }
- }
- #if defined(DEBUG_MODE)
- printf("\n"); // debug of wild compare
- for (i=0; i<11; ++i)
- printf("%c",(na[i]!='\0')?na[i]:' ');
- printf(" ");
- for (i=0; i<11; ++i)
- printf("%02X",na[i]);
- printf(" ");
- for (i=0; i<11; ++i)
- printf("%c",(nb[i]!='\0')?nb[i]:' ');
- printf(" ");
- for (i=0; i<11; ++i)
- printf("%02X",nb[i]);
- #endif
-
- for (i=0; i<11 && (na[i]==nb[i] || na[i]=='\0' || nb[i]=='\0'); i++);
-
- if (i>=11) // strings equal
- return(0);
- else
- return(na[i]-nb[i]); //
- }
-
- /* =========================================== */
- /* Init string for wild-card filenames compare */
- /* =========================================== */
- int wild_init(n,p,q)
- int n; // max length of strings
- char p[],q[]; // p is destination (length n)
- // q is source (MAX length n)
- {
- int i,j;
-
- i=j=0;
- while (i<n) { // process string 'q'
- switch(q[j]) {
- case '?': // single wild char
- p[i++] = '\0'; // matches with any other char
- j++; // proceed with next char
- break;
- case '.': // end of filespec-part
- case ' ': // logical end of string
- case '\0': // end of string
- while (i<n) // fill
- p[i++] = ''; // insert filler chars
- break;
- case '*': // wild string
- while (i<n) // fill
- p[i++] = '\0'; // matches with any other char
- j++; // to next char
- break;
- default: // 'normal' characters
- p[i] = toupper(q[i]); // copy in UPPERcase
- i++; j++; // proceed with next char
- break;
- }
- }
-
- return(j); // displ. of last examined char
- }
-
- /* ==================================================== */
- /* Init string for non-wild-card filenames compare */
- /* No wild-cards expected, no trasnlation to upper case */
- /* ==================================================== */
- int non_wild_init(n,p,q)
- int n; // max length of strings
- char p[],q[]; // p is destination (length n)
- // q is source (MAX length n)
- {
- int i,j;
-
- i=j=0;
- while (i<n) { // process string 'q'
- if (q[j]=='.' || q[j]==' ' || q[j]=='\0') {
- p[i] = ''; // insert filler char
- i++; // rest zeroes (no j-increment!)
- }
- else {
- p[i] = toupper(q[i]); // copy in UPPER case
- i++; j++; // proceed with next char
- }
- }
-
- return(j); // displ. of last examined char
- }
-
- /* ----------------------------------------------- */
- /* Transform file-date into 10-char string */
- /* COUNTRY format mm-dd-yy (USA) or dd-mm-jj (EUR) */
- /* ----------------------------------------------- */
- char *f_date(dat)
- struct _FDATE dat;
- {
- static char date[10] = {'\0'}; // work buffer
- sprintf(date,"%2u%s%02u%s%02u%c",
- ((c_info.fsDateFmt == 0) ? dat.month : dat.day),
- c_info.szDateSeparator,
- ((c_info.fsDateFmt == 0) ? dat.day : dat.month),
- c_info.szDateSeparator,
- (dat.year+80)%100, /* allow 2 digits! */
- '\0');
- return(date);
- }
-
- /* -------------------------------------------------------------- */
- /* Transform file-time into string (hh:mm:ssa) */
- /* COUNTRY format hh:mm:ssa (12 hr USA) or hh-mm-ss (24 hr EUR) */
- /* -------------------------------------------------------------- */
- char *f_time(tim)
- struct _FTIME tim;
- {
- static char time[10] = {'\0'}; // work buffer
- sprintf(time,"%2u%s%02u%s%02u%s%c",
- (c_info.fsTimeFmt==0 && tim.hours>12) ? tim.hours-12 : tim.hours,
- c_info.szTimeSeparator,
- tim.minutes,
- c_info.szTimeSeparator,
- tim.twosecs*2,
- ((c_info.fsTimeFmt==0) ? ((tim.hours>11) ? "p" : "a") : " "),
- '\0');
- return(time);
- }
-
- /* ====================================================== */
- /* Compare for sort on file-date/time + filename + area */
- /* ====================================================== */
- int sort_new(p,q)
- struct _filechain **p,**q;
- {
- int rc;
- ULONG ad,bd,td;
- struct _filechain *a,*b;
-
- a = *p;
- b = *q;
-
- ad = file_time(a->wdate,a->wtime);
- td = file_time(a->cdate,a->ctime);
- if (ad < td) // take latest date
- ad = td;
-
- bd = file_time(b->wdate,b->wtime);
- td = file_time(b->cdate,b->ctime);
- if (bd < td) // take latest date
- bd = td;
-
- if (bd==ad) { // equal timestamps
- rc = strcmp(a->fname,b->fname);
- if (rc) // unequal filenames
- return(rc);
- else
- return(strcmp(a->parea->name,b->parea->name)); // area-code
- }
- else
- return((bd<ad) ? -1 : +1);
- }
-
- /* ========================================= */
- /* Compare for sort on filename + area-code */
- /* ========================================= */
- int sort_gbl(p,q)
- struct _filechain **p,**q;
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *p;
- b = *q;
- rc = strcmp(a->fname,b->fname);
- if (rc) // unequal filename
- return(rc);
- else
- return(strcmp(a->parea->name,b->parea->name)); // area-code
- }
-
- /* ========================================= */
- /* Compare for sort on area code + filename */
- /* ========================================= */
- int sort_all(p,q)
- struct _filechain **p,**q;
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *p;
- b = *q;
- rc = strcmp(a->parea->name,b->parea->name);
- if (rc) // unequal areacode
- return(rc);
- else
- return(strcmp(a->fname,b->fname)); // filename
- }
-
- /* ====================================================== */
- /* Compare for sort on area + file-date/time + filename */
- /* ====================================================== */
- int sort_al2(p,q)
- struct _filechain **p,**q;
- {
- int rc;
- ULONG ad,bd,td;
- struct _filechain *a,*b;
-
- a = *p;
- b = *q;
- rc = strcmp(a->parea->name,b->parea->name);
- if (rc) // unequal area-name
- return(rc);
- else {
- ad = file_time(a->wdate,a->wtime);
- td = file_time(a->cdate,a->ctime);
- if (ad < td) // take latest date
- ad = td;
- bd = file_time(b->wdate,b->wtime);
- td = file_time(b->cdate,b->ctime);
- if (bd < td) // take latest date
- bd = td;
- if (bd!=ad) // unequal date
- return((bd<ad) ? -1 : +1);
- else
- return(strcmp(a->fname,b->fname)); // filename
- }
- }
-
- /* ==================================================== */
- /* Compare for sort on area code + privilege + filename */
- /* No sort on privilege if below area-privilege. */
- /* ==================================================== */
- int sort_fil(p,q)
- struct _filechain **p,**q;
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *p;
- b = *q;
- rc = strcmp(a->parea->name,b->parea->name);
- if (rc) // unequal areacode
- return(rc);
- else {
- if (a->priv <= a->parea->priv && // both within area priv
- b->priv <= b->parea->priv)
- return(strcmp(a->fname,b->fname)); // sort on filename
- else if (a->priv == b->priv) // same privilege
- return(strcmp(a->fname,b->fname)); // filename
- else
- return (a->priv - b->priv); // file priv
- }
- }
-
- /* ========================================== */
- /* Compare for sort on area code of AREA-info*/
- /* ========================================== */
- int sort_summ(p,q)
- struct _downpath *p,*q;
- {
- return(strcmp(p->name,q->name));
- }
-
- /* ---------------------------- */
- /* Sort file-info pointer array */
- /* ---------------------------- */
- void psort(arr, left, right, comp)
- struct _filechain **arr; // pointer to array
- int left,right; // left and right boundaries
- int (*comp)(); // ptr to compare function
- {
- int asc,desc;
- struct _filechain *ref,*tmp;
-
- if ((right-left) < 1) // too few elements
- return;
-
- asc = left; // left 'wall'
- desc = right; // right 'wall'
- ref = arr[(left + right)/2]; // reference value
-
- do {
- while (comp(&arr[asc],&ref) < 0) // move right
- asc++;
- while (comp(&arr[desc],&ref) > 0) // move left
- desc--;
- if (asc <= desc) { // swap
- tmp = arr[desc];
- arr[desc--] = arr[asc];
- arr[asc++] = tmp;
- }
- } while (asc <= desc);
-
- if ((desc-left) < (right-asc)) { // sort smaller part first
- if (left < desc)
- psort(arr, left, desc, comp);
- if (right > asc)
- psort(arr, asc, right, comp);
- }
- else {
- if (right > asc)
- psort(arr, asc, right, comp);
- if (left < desc)
- psort(arr, left, desc, comp);
- }
- }
-
- /* =================== */
- /* determine file-age */
- /* =================== */
- char file_age_ind(fd,ft)
- struct _FDATE fd;
- struct _FTIME ft;
- {
- int age;
-
- age = (int)((time(NULL) - file_time(fd,ft))/86400); // days
- if (age>30)
- return(' '); // older than a month
- else {
- if (age>7) // older than 7 days
- return(DAYS_30);
- else {
- if (age>=0) // non-negative negative age
- return(DAYS_7); // a week
- else
- return('-'); // negative age
- }
- }
- }
-
- /* ============================================ */
- /* Compare for newest acquisition in ALL-list */
- /* ============================================ */
- struct _filechain *new_acq(a,b)
- struct _filechain *a,*b;
- {
- long ad,bd,td;
-
- if (b==NULL) // right might be not assigned
- return(a); // then return first
- ad = file_time(a->wdate,a->wtime);
- td = file_time(a->cdate,a->ctime);
- if (ad < td) // take latest date
- ad = td;
- bd = file_time(b->wdate,b->wtime);
- td = file_time(b->cdate,b->ctime);
- if (bd < td) // take latest date
- bd = td;
- if (ad==bd) // equal dates
- return(b); // (either)
- else
- return((ad>bd) ? a : b); // return most recent
- }
-
- /* ============================================================== */
- /* reformat file-date into long time-value like C time convention */
- /* ============================================================== */
- long file_time(fd,ft)
- struct _FDATE fd; // file date
- struct _FTIME ft; // file time
- {
- static int mon_tab[] = {0,31,59,90,120,151,181,212,243,273,304,334};
- // ignore leapyear February!
- return((((fd.year+10)*1461+1)/4 +
- mon_tab[fd.month-1] +
- fd.day - 1) * 86400L +
- ft.hours * 3600 +
- ft.minutes * 60 +
- ft.twosecs * 2);
- }
-
- /* ============================================================== */
- /* routine to select a substring while skipping leading blanks */
- /* and ending within the boundaries on a word-end. */
- /* Truncate if single word. Respect NL as end of string. */
- /* Return strlen, 0 for NULL-pointer. */
- /* ============================================================== */
- int strsubw(a,b,m)
- char *a,**b; // in-string, start-substring
- int m; // max substring length
- {
- int i,j,k; // counters
-
- if (a==NULL) // NULL pointer
- return(0); // no string
-
- for (i=0; a[i] == ' '; ++i); // skip leading blanks
- a = *b = a+i; // offset to first non-blank char
- for (i=0; a[i] != '\0' && a[i]!='\n'; ++i); // search end string
- if (i==0) // nothing left
- return(0); // end!
-
- for (k=0; k<m && k<i; ++k); // maximum substring
- if (k<i) { // there is more in string
- if (a[k]==' ' || a[k]=='\n' || a[k]=='\0'); // word boundary
- else {
- for (j=k-1; j>0 && a[j]!=' '; --j); // try to remove 'split' word
- if (j>0) // any space found?
- k = j; // OK, else split!
- }
- }
- for (; k>0 && a[k-1] == ' '; --k); // remove trailing blanks
- return(k); // return length of substring
- // b contains start-point
- }
-
- /* ====================================================== */
- /* Function to locate next non-blank character in buffer. */
- /* Returns pointer to word or NULL-ptr if no next word. */
- /* ====================================================== */
- char *next_word(line)
- char *line; //
- {
- unsigned int i;
-
- for (i=0; line[i]!=' ' && // skip non-blanks
- line[i]!='\n' &&
- line[i]!='\0'; ++i);
- for ( ; line[i]==' '; ++i); // skip blanks
- if (line[i] != '\0' &&
- line[i] != '\n')
- return(line+i); // next word found
- else
- return(NULL); // NULL if no next word
- }
-
- /* =========================================== */
- /* Function to make ASCIIZ string of ONE word. */
- /* =========================================== */
- char *asciiz(buf)
- char *buf;
- {
- unsigned int i;
- static char buf2[255]; // return buffer
-
- for (i=0; buf[i] != ' ' && // end copy at first blank
- buf[i] !='\n' && // or end of line
- buf[i] !='\0'; ++i) // or end of string
- buf2[i] = buf[i]; // copy
- buf2[i] = '\0'; // end of string
- return(buf2); // pointer to ASCIIZ string
- }
-
- /* ================================== */
- /* some marketing below every report! */
- /* ================================== */
- void signature(pf,now)
- FILE *pf; // file pointer
- char *now; // timestamp string
- {
- static char *mode[] = {"DOS","OS/2"};
-
- fprintf(pf,"\n\n %-.40s%-.28s",HD,HD);
- fprintf(pf,"\n %s %d.%d%c by %s, on %s under %s %d.%d ",
- PROGNAME,VERSION,SUBVERS,SUFFIX,AUTHOR,now,
- mode[_osmode & 1],
- _osmajor/((_osmode)?10:1),
- _osminor/10);
- fprintf(pf,"\n %-.40s%-.28s\n",HD,HD);
- }
-
- /* ================ */
- /* HELP information */
- /* ================ */
- void show_help()
- {
- printf("\nSyntax: DOWNSORT [commandline-parameters]\n");
- printf("\n@filespec - Filespec of Configuration file with processing parameters");
- printf("\nBBS[:p] - Make BBS-list ╗");
- printf("\nNEW[:pp] - Make NEW-list(s) ╠═ for 1 or more privilege levels");
- printf("\nALL[:pp] - Make ALL-list(s) ║");
- printf("\nGBL[:pp] - Make GBL-list(s) ╝");
- printf("\nFIL[:fpath] - (Re-)create FILES.BBS files");
- printf("\n-T|W - All long file descriptions to be Truncated or Wrapped");
- printf("\n-A|D - Files to be sorted Alphabetically or on Date");
- printf("\n-H|Q|V - Display this HELP-screen, or run Quietly or Verbose");
- printf("\n");
- printf("\n - p : first letter of privilege (i.e. D=Disgrace, N=Normal, etc).");
- printf("\n - pp : list generated for each specified privilege.");
- printf("\n - fpath : output directory of FILES.BBS files.");
- printf("\n\nThese parameters override program and configurationfile values.");
- printf("\nRead documentation or sample configuration file "
- "for details and defaults.\n");
- exit(1);
- }
-
-