/* ============================================================= */ /* Rob Hamerling's MAXIMUS download file scan and sort utility. */ /* -> Collection of general service routines for DOWNSORT. */ /* ============================================================= */ // #define DEBUG_MODE #define INCL_BASE #include #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 (i12) ? 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((bdfname,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((bdfname,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; k0 && 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); }