home *** CD-ROM | disk | FTP | other *** search
- /* ============================================================= */
- /* Rob Hamerling's MAXIMUS download file scan and sort utility. */
- /* -> DOWNSRV.C */
- /* -> Collection of general service routines for DOWNSORT. */
- /* ============================================================= */
-
- #define INCL_BASE
- #include <os2.h>
-
- #include <ctype.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include "downsort.h"
- #include "downfpro.h"
-
- /* function prototype of local functions */
-
- int comp_area(struct _downpath huge *, struct _downpath huge *);
-
-
- /* ------------------- */
- /* Welcome to the user */
- /* ------------------- */
- void show_welcome(void)
- {
- static char HD[22] = "══════════════════════";
- printf("\n%15s╔%.22s╗\n", "", HD);
- printf("╔%.14s╣ %8.8s version %c.%c%c╠%.15s╗\n",
- HD,PROGNAME,VERSION,SUBVERS,SUFFIX,HD);
- printf("║ Copyright ╚%.22s╝ Shareware ║\n", HD);
- printf("║ %s %-38.38s║\n", MAX,PROGDESC);
- printf("║ by %-13.13s, %-29s║\n", AUTHOR,CITY);
- printf("║%-29s%24s║\n", PHONE, FIDO);
- printf("╚%.22s%.22s%.9s╝\n", HD, HD, HD);
- }
-
- /* ======================================================== */
- /* Compare two filenames. */
- /* First name must be regular "8.3" format filename. */
- /* Second name may contain wildcards. */
- /* ======================================================== */
- int wild_comp(char a[],
- char b[])
- {
- int i;
- char na[11], nb[11]; // formatted filename fields
- // keep 'm for subsequent calls
- static char empty_ext[] = { "..." }; // 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
- i = non_wild_init(3,na+8,a+i); // pseudo extension
- break;
- }
-
- 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: // invalid filename
- i = wild_init(3,nb+8,b+i); // pseaudo extension
- break;
- }
-
- #if defined(DEBUG2)
- 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("%02.2X", na[i]);
- printf(" ");
- for (i=0; i<11; ++i)
- printf("%c", (nb[i] != '\0') ? nb[i] : ' ');
- printf(" ");
- for (i=0; i<11; ++i)
- printf("%02.2X", nb[i]);
- #endif
-
- // for (i=0; i<11 && (na[i]==nb[i] || na[i]=='\0' || nb[i]=='\0'); i++);
- for (i=0; i<11 && (na[i]==nb[i] || nb[i]=='\0'); i++);
-
- #if defined(DEBUG2)
- printf(" =#=%d",i); // debug of wild compare
- #endif
- if (i>=11) // strings equal
- return(0);
- else
- return(na[i]-nb[i]); //
- }
-
- /* ============================================ */
- /* Init string for wild-card filenames compare. */
- /* Translation to UPPER case. */
- /* ============================================ */
- int wild_init(short int n,
- char p[],
- char q[])
- {
- 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] = (char) toupper(q[i]); // convert to UPPERcase and copy
- 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, translation to upper case. */
- /* ==================================================== */
- int non_wild_init(short int n,
- char p[],
- char q[])
- {
- 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 filler (no j-increment!)
- }
- else {
- p[i] = (char) toupper(q[i]); // to UPPERcase and copy
- i++; j++; // proceed with next char
- }
- }
-
- return(j); // displ. of last examined char
- }
-
- /* ------------------ */
- /* Produce time stamp */
- /* ------------------ */
- char *sys_date(char t[])
- {
- long int secs_now; // relative time value
- char *buf; // pointer to time string
-
- time(&secs_now); // get current time
- buf = ctime(&secs_now); // convert to char string
- strcpy(t,buf); // copy string
- t[16] = '\0'; // undo secs, year and newline
- return(t); // pointer to buffer
- }
-
- /* ------------------------------------------------- */
- /* Transform file-date into a 9-char string */
- /* COUNTRY format mm-dd-yy (USA) or dd-mm-jj (EUR) */
- /* ------------------------------------------------- */
- char *f_date(struct _FDATE date)
- {
- static char string[9]; // work buffer
- sprintf(string,"%2u%s%02u%s%02u",
- ((c_info.fsDateFmt == 0) ? date.month : date.day),
- c_info.szDateSeparator,
- ((c_info.fsDateFmt == 0) ? date.day : date.month),
- c_info.szDateSeparator,
- (date.year+80)%100); /* allow 2 digits! */
- return(string);
- }
-
- /* =================== */
- /* determine file-age */
- /* =================== */
- char file_age_ind(struct _FDATE fd,
- struct _FTIME ft)
- {
- short 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
- }
- }
- }
-
- /* -------------------------------------------------- */
- /* Transform file-size and date into a 15-byte string */
- /* Size in K (rounded to next higher number KBytes) */
- /* Date format as inf_date(), plus age indicator. */
- /* If date zero: pointer to 'offline'-text. */
- /* -------------------------------------------------- */
- char *f_size_date(unsigned long int size,
- struct _FDATE wdate,
- struct _FDATE cdate,
- struct _FTIME ctime)
- {
- static char string[15]; // work buffer
- if (wdate.day) { // date non-zero
- sprintf(string,"%4luK ", (size+1023)/1024); // format size
- strcat(string, f_date(wdate)); // add formatted date
- string[14] = file_age_ind(cdate, ctime); // add age ind.
- string[15] = '\0'; // end of string
- return(string); // for 'online' file
- }
- else
- return(OFFLINE); // for 'offline' file
- }
-
- /* -------------------------------------------------------------- */
- /* 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(struct _FTIME tim)
- {
- static char time[7] = {'\0'}; // work buffer
- sprintf(time,"%2u%s%02u%c%c",
- (c_info.fsTimeFmt==0 && tim.hours>12) ? tim.hours-12 : tim.hours,
- c_info.szTimeSeparator,
- tim.minutes,
- ((c_info.fsTimeFmt==0) ? ((tim.hours>11) ? 'p' : 'a') : ' '),
- '\0');
- return(time);
- }
-
- /* ------------------------------ */
- /* Build pointer-array for sorts */
- /* ------------------------------ */
- struct _filechain **prep_sort(unsigned short int cnt,
- struct _filechain *chn)
- {
- unsigned short int i; // counter
- struct _filechain **dm; // pointer to file-sort array
- struct _filechain *ca; // pointer to fileinfo (chain)
-
- dm = (struct _filechain **)malloc(cnt*sizeof(struct _filechain *));
- if (dm == NULL) { // not enough memory
- printf(MSG_MEM,PROGNAME);
- exit(11);
- }
- ca = chn; // ptr to first file-info
- for (i=0; ca != NULL; i++) { // init sort array
- dm[i] = ca;
- ca = ca->next_element;
- }
- return(dm);
- }
-
- /* ====================================================== */
- /* Compare for sort on file-date/time + filename + area */
- /* ====================================================== */
- int sort_new(const void *p,
- const void *q)
- {
- int rc;
- unsigned long int ad,bd,td;
- struct _filechain *a,*b;
-
- a = *(struct _filechain **)p;
- b = *(struct _filechain **)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(comp_area(a->parea, b->parea));
- }
- else
- return( (int)((bd<ad) ? -1 : +1) );
- }
-
- /* ========================================= */
- /* Compare for sort on filename + area-name */
- /* ========================================= */
- int sort_gbl(const void *p,
- const void *q)
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *(struct _filechain **)p;
- b = *(struct _filechain **)q;
- rc = strcmp(a->fname,b->fname);
- if (rc) // unequal filename
- return(rc);
- else
- return(comp_area(a->parea, b->parea));
- }
-
- /* ======================================== */
- /* Compare for sort on areaname + filename */
- /* ======================================== */
- int sort_all(const void *p,
- const void *q)
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *(struct _filechain **)p;
- b = *(struct _filechain **)q;
- rc = comp_area(a->parea, b->parea);
- if (rc) // unequal areacode
- return(rc);
- else
- return(strcmp(a->fname,b->fname)); // filename
- }
-
- /* ======================================================== */
- /* Compare for sort on areaname + file-date/time + filename */
- /* ======================================================== */
- int sort_al2(const void *p,
- const void *q)
- {
- int rc;
- unsigned long int ad,bd,td;
- struct _filechain *a,*b;
-
- a = *(struct _filechain **)p;
- b = *(struct _filechain **)q;
- rc = comp_area(a->parea, b->parea);
- 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( (int)((bd<ad) ? -1 : +1) );
- else
- return(strcmp(a->fname,b->fname)); // filename
- }
- }
-
- /* ======================================================== */
- /* Compare for sort on areaname + FILES.BBS sequence number */
- /* ======================================================== */
- int sort_akp(const void *p,
- const void *q)
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *(struct _filechain **)p;
- b = *(struct _filechain **)q;
- rc = comp_area(a->parea, b->parea);
- if (rc) // unequal areacode
- return(rc);
- else {
- if (a->fseq != b->fseq) // unequal sequence number
- return( (int)((a->fseq < b->fseq) ? -1 : +1) );
- else
- return(0); // equal sequence number */
- }
- }
-
- /* =================================================== */
- /* Compare for sort on areaname + privilege + filename */
- /* No sort on privilege if below area-privilege. */
- /* =================================================== */
- int sort_fil(const void *p,
- const void *q)
- {
- int rc;
- struct _filechain *a,*b;
-
- a = *(struct _filechain **)p;
- b = *(struct _filechain **)q;
- rc = comp_area(a->parea, b->parea);
- 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( (int)(a->priv - b->priv) ); // file priv
- }
- }
-
- /* ========================================= */
- /* Compare for sort on areaname of AREA-info */
- /* ========================================= */
- int sort_summ(const void *p,
- const void *q)
- {
- return( comp_area((struct _downpath huge *)p, (struct _downpath huge *)q) );
- }
-
- /* ========================================= */
- /* Compare for sort on areaname of AREA-info */
- /* ========================================= */
- int comp_area(struct _downpath huge *p,
- struct _downpath huge *q)
- {
- int x,y; // offsets in area_IN_EX
-
- switch(area_seq) {
- case KEEPSEQ: return(p->anum - q->anum);
- break;
- case ALPHA: return(stricmp(p->name, q->name));
- break;
- case INCLUDE: if (area_IN_EX == +1) { // areaINclude used
- for (x=0; strcmp(selected_area[x], EMPTY) &&
- stricmp(selected_area[x], p->name);
- x++); // just determine x
- for (y=0; strcmp(selected_area[y], EMPTY) &&
- stricmp(selected_area[y], q->name);
- y++); // just determine y
- if (x!=y) { // if not equal
- return(x - y); // relative position
- break; // only if destinctive
- }
- }
- // may fall back to group-order
- case GROUP: // is default
- default: return(stricmp(p->ename, q->ename));
- break;
- }
- }
-
- /* ---------------------------- */
- /* Sort file-info pointer array */
- /* ---------------------------- */
- void psort(struct _filechain **arr,
- short int left,
- short int right,
- int (*comp)(const void *, const void *))
- {
- 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);
- }
- }
-
- /* ============================================ */
- /* Compare for newest acquisition in ALL-list */
- /* ============================================ */
- struct _filechain *new_acq(struct _filechain *a,
- struct _filechain *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 int file_time(struct _FDATE fd,
- struct _FTIME ft)
- {
- 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);
- }
-
- /* =================================== */
- /* Include a text file into a report. */
- /* Output file is supposed to be open! */
- /* =================================== */
- void file_incl(FILE *pfo, // output file pointer
- unsigned int fl) // filelist id
- {
- char buf[MAXRCD]; // I/O buffer
- FILE *pfi; // input file pointer
-
- if (lp[fl].incl_fspec != NULL) { // filespec present
- if ((pfi = fopen(lp[fl].incl_fspec,"rt")) != NULL) {
- while (fgets(buf,MAXRCD,pfi) != NULL) // all records "as is"
- fputs(buf,pfo);
- fclose(pfi);
- }
- else {
- if (oper_mode == VERBOSE) // report only in verbose mode
- printf(MSG_TRL,lp[fl].incl_fspec); // file not included
- }
- }
- }
-
- /* --------------------------------------------------------------- */
- /* Produce file description parts for first and continuation lines */
- /* --------------------------------------------------------------- */
- void desc_part(FILE *pf, /* output file pointer */
- char *desc, /* complete description */
- unsigned int l1, /* length 1st part of descr. */
- unsigned int l2, /* length of subsequent parts */
- unsigned int fl) /* report structure index */
- {
- unsigned int k,n; /* length of part of string */
- char *p; /* pointer to output string */
-
- if (k = strsubw(desc, &p, l1)) { /* length (max = l1) */
- if (lp[fl].wrapflag != WRAP) { /* truncate */
- n = strlen(desc); /* total string length */
- k = (l1 > n) ? n : l1; /* shortest of l1 and n */
- }
- fprintf(pf,"%-.*s\n", k, p); /* (1st part of) string */
- while (k>0 && lp[fl].wrapflag==WRAP) /* more parts */
- if (k = strsubw(p+k, &p, l2)) /* subseq. part */
- fprintf(pf,"%*s%-.*s\n", 79-l2,"", k, p); /* 2nd+ descr parts */
- }
- }
-
- /* ============================================================== */
- /* 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. */
- /* ============================================================== */
- short int strsubw(char *a,
- char **b,
- short int m)
- {
- short 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]!='\r' && a[i]!='\n'; ++i); // search end
- 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]=='\r' || a[k]=='\n' || a[k]=='\0'); // word end
- 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(char *line)
- {
- unsigned int i;
-
- for (i=0; line[i]!=' ' && // skip non-blanks
- line[i]!='\r' &&
- line[i]!='\n' &&
- line[i]!='\0'; ++i);
- for ( ; line[i]==' '; ++i); // skip blanks
- if (line[i] != '\0' &&
- line[i] != '\r' &&
- 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(char *buf)
- {
- unsigned short int i;
-
- for (i=0; buf[i] != ' ' && // end copy at first blank
- buf[i] !='\r' && // CR character
- buf[i] !='\n' && // LF character
- 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
- }
-
- /* ============================================ */
- /* Function to strip off AVATAR codes in string */
- /* ============================================ */
- char *strava(char *buf)
- {
- unsigned short int i, j, k;
-
- k = strlen(buf); // length of source string
- for (i=j=0; i < k; ) { // whole input string
- // printf("\nbuf[%02u]=%02d j=%u", i, buf[i], j);
- switch(buf[i]) {
- case AVA_V: switch(buf[i+1]) {
- case AVA_A: ++i; ++i; ++i; break; // jump 3
- case AVA_C:
- case AVA_D:
- case AVA_E:
- case AVA_F:
- case AVA_G: ++i; ++i; break; // jump 2
- case AVA_H: ++i; ++i; ++i; ++i; break; // jump 4
- default: buf2[j++]=buf[i++]; break;
- }
- break;
- case AVA_G:
- case AVA_H:
- case AVA_I:
- // case AVA_J:
- case AVA_L:
- // case AVA_M:
- ++i; // skip 1 char
- break;
- case '-': if (i==0) /* first character */
- ++i; /* skip 1 char */
- else
- buf2[j++] = buf[i++]; /* copy */
- break;
- default: buf2[j++] = buf[i++];
- break;
- }
- }
- buf2[j] = '\0'; // end of string
- return(buf2); // pointer to ASCIIZ string
- }
-
- /* ========================================================= */
- /* creates filecount and bytecount per area within privilege */
- /* and pointer to most recent file in area */
- /* returns total filecount all area's within priv. */
- /* should be run before calling other count_functions below. */
- /* ========================================================= */
- unsigned int preproc_area(struct _downpath huge *area,
- struct _filechain **dm,
- short int priv)
- {
- unsigned int i; // counter
- unsigned int fpc; // total filecount within priv
-
- for (i=0; i<area_total_count; i++) { // all area's in array
- area[i].file_count = 0; // init filecount per area
- area[i].byte_count = 0L; // init bytecount per area
- area[i].newest = NULL; // null most-recent
- }
- for (i=0; i<file_total_count; i++) { // scan file-chain
- if (dm[i]->priv <= priv && // file within privilege
- dm[i]->fname[0] != '\0') { // not a 'comment' entry
- dm[i]->parea->file_count++; // increment area filecount
- dm[i]->parea->byte_count += dm[i]->size; // add filesize
- dm[i]->parea->newest = new_acq(dm[i], dm[i]->parea->newest);
- }
- }
- fpc = 0; // init total filecount
- for (i=0; i<area_total_count; i++) // all area's in array
- fpc += area[i].file_count; // sum of area file_counts
- return(fpc); // return total file_count
- }
-
- /* =========================================== */
- /* count areas within privilege for top-header */
- /* works only correctly after count_priv_files */
- /* =========================================== */
- unsigned int count_areas(struct _downpath huge *area,
- short int p)
- {
- unsigned int i,j;
-
- for (i=j=0; i<area_total_count; i++) // whole area-array
- if (area[i].priv <= p && // area within privilege
- area[i].file_count > 0) // any files
- ++j; // add to area_count
- return(j); // return areas within priv.
- }
-
- /* ================================================ */
- /* (re-)Count files within privilege for top-header */
- /* (file_priv_count already returns file-count) */
- /* Works only correctly after preproc_area(). */
- /* ================================================ */
- unsigned int count_files(struct _downpath huge *area)
- {
- unsigned int i,f;
-
- for (i=f=0; i<area_total_count; i++) // scan area array
- f += area[i].file_count; // add to file_count
- return(f); // return files within priv.
- }
-
- /* =========================================== */
- /* count bytes within privilege for top-header */
- /* works only correctly after count_priv_files */
- /* =========================================== */
- unsigned long int count_bytes(struct _downpath huge *area)
- {
- unsigned short int i; // counter
- unsigned long b; // byte count
-
- for (i=0,b=0L; i<area_total_count; i++) // scan area array
- b += area[i].byte_count; // add to byte_count
- return(b); // return bytes within priv.
- }
-
- /* ==================================== */
- /* insert title lines from DOWNSORT.CFG */
- /* ==================================== */
- void insert_title(FILE *pf,
- char *title[],
- int ipf) // if not zero: call stripf()
- {
- int i;
-
- for (i=0; i<MAXTIT && title[i]!=NULL; ++i) // all lines
- fprintf(pf,"%s\n",
- (ipf) ? stripf(title[i]) : title[i]); // 1 line
- }
-
- /* ============================================================ */
- /* insert separator line, variable number, separated by 1 blank */
- /* ============================================================ */
- void sep_line(FILE *pf, // output file pointer
- char c, // separator char
- unsigned short int size,...) // length(s)
- {
- char buf[80]; // work buffer
- unsigned short int k,ll; // counts
- va_list mk; // argument marker
-
- memset(buf, c, 79); // whole line buffer
- va_start(mk, size); // start variable arg processing
- ll = size; // take first
- k = 0;
- while (ll > 0 && k < 80) { // all parts of line
- k += ll; // adjust offset
- if ((ll = va_arg(mk, unsigned short int)) > 0) // next argument
- buf[k++] = ' '; // insert space
- }
- buf[k] = '\0'; // last blank: end of string
- fprintf(pf, "%-s\n", buf); // output
- va_end(mk); // end variable argument list
- }
-
- /* ================== */
- /* insert BLOCK title */
- /* =================== */
- void block_title(FILE *pf,
- short int n,
- char *title,
- unsigned int listfile)
- {
- unsigned short int i;
-
- for (i=0; i<title_lines[lp[listfile].tfont]; ++i) // whole title
- fprintf(pf, "%s\n", strnblk(title, n, lp[listfile].tfont,i));
- }
-
- /* ================================== */
- /* some marketing below every report! */
- /* ================================== */
- void signature(FILE *pf,
- char *now)
- {
- static char *mode[] = {"DOS","OS/2"};
-
- fprintf(pf,"\n\n ");
- sep_line(pf, '═', 68, 0);
- fprintf(pf," This list was created with %s %c.%c%c by %s\n"
- " on %s under %s %d.%d\n ",
- PROGNAME,VERSION,SUBVERS,SUFFIX,AUTHOR,now,
- mode[_osmode & 1],
- _osmajor/((_osmode)?10:1),
- _osminor/10);
- sep_line(pf, '═', 68, 0);
- fprintf(pf, "\n"); // extra space
- }
-
- /* ================ */
- /* HELP information */
- /* ================ */
- void show_help(void)
- {
- static char *help[] = {
- "\nSyntax: DOWNSORT [commandline-parameters]\n",
- "\n@filespec - Filespec of configuration file with processing parameters",
- "\nBBS[:p] - Make BBS-list ───┐",
- "\nNEW[:pp] - Make NEW-list(s) │",
- "\nEMI[:pp] - Make EMI-list(s) │ │for 1 or more privileges, where:",
- "\nALL[:pp] - Make ALL-list(s) ├─┤ p = first letter of privilege",
- "\nIPF[:pp] - Make IPF-list(s) │ │ pp = max 10 privilege letters",
- "\nGBL[:pp] - Make GBL-list(s) │ (N=Normal, P=Privil, etc)",
- "\nOK[:pp] - Make OKFile(s) │",
- "\nDUP[:p] - Make DUP-list ───┘",
- "\nORP - Make ORP-list (if ORPHANS detected)",
- "\nFIL[:fpath] - (re-)Create FILES.BBS files [in directory 'fpath']",
- "\nnnn[P] - Limit NEW- and BBS-list by number, or age if P=D|W|M",
- "\n-T|W - Long file descriptions to be Truncated or Wrapped",
- "\n-A|D|K - Sort files Alphabetically, on Date, or Keep in FILES.BBS-seq.",
- "\n-H|Q|V - Display this HELP-screen, or run Quietly or Verbose",
- "\n-X - eXclude privilege indications in the lists",
- "\n───────────",
- "\nCommandline parameters override program and configuration-file values."
- "\nRead documentation and sample configuration file for details and defaults.",
- NULL};
-
- int i;
- for (i=0; help[i]; ++i)
- printf(help[i]);
- exit(1);
- }
-
-