home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
com
/
bbs
/
downsrt
/
source
/
downsrv.c
< prev
next >
Wrap
Text File
|
1991-06-05
|
23KB
|
654 lines
/* ============================================================= */
/* 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 "ctype.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "time.h"
#include "downsort.h"
/* ------------------- */
/* Welcome to the user */
/* ------------------- */
void show_welcome()
{
printf("\n%15s╔%22.22s╗", "",HD);
printf("\n╔%14.14s╣ %8.8s version %c.%c%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║%-29s%24s║", 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 + FILES.BBS sequence number */
/* ========================================================= */
int sort_akp(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->fseq != b->fseq) // unequal sequence number
return((a->fseq < b->fseq) ? -1 : +1);
else
return(0); // equal sequence number */
}
}
/* ==================================================== */
/* 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)(void *, void *); // 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);
}
/* =================================== */
/* include a test file into a report */
/* output file is supposed to be open! */
/* =================================== */
void file_incl(pfo, fn)
FILE *pfo; // output file pointer
char *fn; // input filespec
{
char buf[MAXRCD]; // I/O buffer
FILE *pfi; // input file pointer
if ((pfi = fopen(fn,"rt")) != NULL) {
while (fgets(buf,MAXRCD,pfi) != NULL) // all records "as is"
fputs(buf,pfo);
fclose(pfi);
}
else
printf(MSG_TRL,fn); // file not included
}
/* ============================================================== */
/* 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 %c.%c%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);
}
/* =========================================== */
/* count areas within privilege for top-header */
/* =========================================== */
USHORT count_areas(area, p)
struct _downpath *area; // pointer to area array
int p; // privilege for count
{
USHORT i,j;
for (i=j=0; i<area_count; i++) // whole area-array
if (area[i].priv <= p && // consider only within privilege
area[i].file_count > 0) // and only if files present
++j; // add to count
return(j);
}
/* =========================================== */
/* count bytes within privilege for top-header */
/* =========================================== */
ULONG count_bytes(dm, p)
struct _filechain **dm; // pointer to file-sort array
int p; // privilege for count
{
USHORT i;
ULONG b;
for (i=0,b=0L; i<file_count; i++) // scan whole file-chain
if (dm[i]->priv <= p) // consider only within privilege
b += dm[i]->size; // add to count
return(b);
}
/* =========================================== */
/* count files within privilege for top-header */
/* =========================================== */
USHORT count_files(dm, p)
struct _filechain **dm; // pointer to file-sort array
int p; // privilege for count
{
USHORT i,j;
for (i=j=0; i<file_count; i++) // scan whole file-chain
if (dm[i]->priv <= p) // consider only within privilege
++j; // add to count
return(j);
}
/* ================ */
/* 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) ║");
printf("\nALL[:pp] - Make ALL-list(s) ╠═ for 1 or more privilege levels");
printf("\nIPF[:pp] - Make IPF-list(s) ║");
printf("\nGBL[:pp] - Make GBL-list(s) ═╝");
printf("\nORP - Make ORP-list (if ORPHANS detected)");
printf("\nFIL[:fpath] - (re-)Create FILES.BBS files");
printf("\nnnn - (numeric) List only the first nnn files (NEW- and BBS-list)");
printf("\n-T|W - All long file descriptions to be Truncated or Wrapped");
printf("\n-A|D|K - Sort files Alphabetically, on Date, or Keep in FILES.BBS-seq.");
printf("\n-H|Q|V - Display this HELP-screen, or run Quietly or Verbose");
printf("\n-X - eXclude privilege indications in the FileLists");
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);
}