|
|
2.30b OS/2
#line 1 "MISC.C"
/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
/***************************************************************************/
/* Miscellaneous functions that are useful many places throughout the code */
/***************************************************************************/
#include "sbbs.h"
#include "crc32.h"
#ifdef __WIN32__
#include <windows.h> // Required for kbd_state(), beep(), and mswait()
#endif
/****************************************************************************/
/* Returns the number of characters in 'str' not counting ctrl-ax codes */
/* or the null terminator */
/****************************************************************************/
int bstrlen(char *str)
{
int i=0;
while(*str) {
if(*str==1) /* ctrl-a */
str++;
else
i++;
if(!(*str)) break;
str++; }
return(i);
}
void strip_ctrl(char *str)
{
char tmp[1024];
int i,j,k;
k=strlen(str);
for(i=j=0;i<k;i++)
if(str[i]==1) /* Ctrl-a */
i++;
else if(j && str[i]<=SP && tmp[j-1]==SP)
continue;
else if(i && !isalnum(str[i]) && str[i]==str[i-1])
continue;
else if((uchar)str[i]>=SP)
tmp[j++]=str[i];
else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
tmp[j++]=SP;
tmp[j]=0;
strcpy(str,tmp);
}
void strip_exascii(char *str)
{
char tmp[1024];
int i,j,k;
k=strlen(str);
for(i=j=0;i<k;i++)
if(!(str[i]&0x80))
tmp[j++]=str[i];
tmp[j]=0;
strcpy(str,tmp);
}
/****************************************************************************/
/* Returns in 'string' a character representation of the number in l with */
/* commas. */
/****************************************************************************/
char *ultoac(ulong l, char *string)
{
char str[256];
char i,j,k;
ultoa(l,str,10);
i=strlen(str)-1;
j=i/3+1+i;
string[j--]=0;
for(k=1;i>-1;k++) {
string[j--]=str[i--];
if(j>0 && !(k%3))
string[j--]=','; }
return(string);
}
/****************************************************************************/
/* Network open function. Opens all files DENYALL and retries LOOP_NOPEN */
/* number of times if the attempted file is already open or denying access */
/* for some other reason. All files are opened in BINARY mode. */
/****************************************************************************/
int nopen(char *str, int access)
{
char logstr[256];
int file,share,count=0;
if(access&O_DENYNONE) {
share=SH_DENYNO;
access&=~O_DENYNONE; }
else if(access==O_RDONLY) share=SH_DENYWR;
else share=SH_DENYRW;
while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
&& errno==EACCES && count++<LOOP_NOPEN)
if(count>10)
mswait(55);
if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN) {
sprintf(logstr,"NOPEN COLLISION - File: %s Count: %d"
,str,count);
logline("!!",logstr); }
if(file==-1 && errno==EACCES)
bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
return(file);
}
/****************************************************************************/
/* This function performs an nopen, but returns a file stream with a buffer */
/* allocated. */
/****************************************************************************/
FILE *fnopen(int *file, char *str, int access)
{
char mode[128];
FILE *stream;
if(((*file)=nopen(str,access))==-1)
return(NULL);
if(access&O_APPEND) {
if(access&O_RDONLY)
strcpy(mode,"a+");
else
strcpy(mode,"a"); }
else {
if(access&O_WRONLY)
strcpy(mode,"r+");
else
strcpy(mode,"r"); }
stream=fdopen((*file),mode);
if(stream==NULL) {
close(*file);
errormsg(WHERE,ERR_FDOPEN,str,access);
return(NULL); }
setvbuf(stream,NULL,_IOFBF,2*1024);
return(stream);
}
#ifndef __FLAT__
/****************************************************************************/
/* This function reads files that are potentially larger than 32k. */
/* Up to one megabyte of data can be read with each call. */
/****************************************************************************/
long lread(int file, char huge *buf,long bytes)
{
long count;
for(count=bytes;count>32767;count-=32767,buf+=32767)
if(read(file,(char *)buf,32767)!=32767)
return(-1L);
if(read(file,(char *)buf,(int)count)!=count)
return(-1L);
return(bytes);
}
long lfread(char huge *buf, long bytes, FILE *fp)
{
long count;
for(count=bytes;count>0x7fff;count-=0x7fff,buf+=0x7fff)
if(fread((char *)buf,1,0x7fff,fp)!=0x7fff)
return(0);
if(fread((char *)buf,1,(int)count,fp)!=count)
return(0);
return(bytes);
}
/****************************************************************************/
/* This function writes files that are potentially larger than 32767 bytes */
/* Up to one megabytes of data can be written with each call. */
/****************************************************************************/
long lwrite(int file, char huge *buf, long bytes)
{
long count;
for(count=bytes;count>32767;count-=32767,buf+=32767)
if(write(file,(char *)buf,32767)!=32767)
return(-1L);
if(write(file,(char *)buf,(int)count)!=count)
return(-1L);
return(bytes);
}
#endif
/****************************************************************************/
/* Truncates white-space chars off end of 'str' and terminates at first tab */
/****************************************************************************/
void truncsp(char *str)
{
uint c;
str[strcspn(str,"\t")]=0;
c=strlen(str);
while(c && (uchar)str[c-1]<=SP) c--;
str[c]=0;
}
/****************************************************************************/
/* Puts a backslash on path strings */
/****************************************************************************/
void backslash(char *str)
{
int i;
i=strlen(str);
if(i && str[i-1]!='\\') {
str[i]='\\'; str[i+1]=0; }
}
/****************************************************************************/
/* Puts a backslash on path strings if not just a drive letter and colon */
/****************************************************************************/
void backslashcolon(char *str)
{
int i;
i=strlen(str);
if(i && str[i-1]!='\\' && str[i-1]!=':') {
str[i]='\\'; str[i+1]=0; }
}
/****************************************************************************/
/* Updates 16-bit "rcrc" with character 'ch' */
/****************************************************************************/
void ucrc16(uchar ch, ushort *rcrc) {
ushort i, cy;
uchar nch=ch;
for (i=0; i<8; i++) {
cy=*rcrc & 0x8000;
*rcrc<<=1;
if (nch & 0x80) *rcrc |= 1;
nch<<=1;
if (cy) *rcrc ^= 0x1021; }
}
/****************************************************************************/
/* Returns CRC-16 of string (not including terminating NULL) */
/****************************************************************************/
ushort crc16(char *str)
{
int i=0;
ushort crc=0;
ucrc16(0,&crc);
while(str[i])
ucrc16(str[i++],&crc);
ucrc16(0,&crc);
ucrc16(0,&crc);
return(crc);
}
/****************************************************************************/
/* Returns CRC-32 of string (not including terminating NULL) */
/****************************************************************************/
ulong crc32(char *buf, ulong len)
{
ulong l,crc=0xffffffff;
for(l=0;l<len;l++)
crc=ucrc32(buf[l],crc);
return(~crc);
}
/****************************************************************************/
/* Compares pointers to pointers to char. Used in conjuction with qsort() */
/****************************************************************************/
int pstrcmp(char **str1, char **str2)
{
return(strcmp(*str1,*str2));
}
/****************************************************************************/
/* Returns the number of characters that are the same between str1 and str2 */
/****************************************************************************/
int strsame(char *str1, char *str2)
{
int i,j=0;
for(i=0;i<strlen(str1);i++)
if(str1[i]==str2[i]) j++;
return(j);
}
#define MV_BUFLEN 4096
/****************************************************************************/
/* Moves or copies a file from one dir to another */
/* both 'src' and 'dest' must contain full path and filename */
/* returns 0 if successful, -1 if error */
/****************************************************************************/
int mv(char *src, char *dest, char copy)
{
char str[256],*buf,atr=curatr;
int ind,outd;
long length,chunk=MV_BUFLEN,l;
struct ftime ftime;
FILE *inp,*outp;
if(!stricmp(src,dest)) /* source and destination are the same! */
return(0);
if(!fexist(src)) {
bprintf("\r\n\7MV ERROR: Source doesn't exist\r\n'%s'\r\n"
,src);
return(-1); }
if(!copy && fexist(dest)) {
bprintf("\r\n\7MV ERROR: Destination already exists\r\n'%s'\r\n"
,dest);
return(-1); }
if(!copy && ((src[1]!=':' && dest[1]!=':')
|| (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
if(rename(src,dest)) { /* same drive, so move */
bprintf("\r\nMV ERROR: Error renaming '%s'"
"\r\n to '%s'\r\n\7",src,dest);
return(-1); }
return(0); }
attr(WHITE);
if((ind=nopen(src,O_RDONLY))==-1) {
errormsg(WHERE,ERR_OPEN,src,O_RDONLY);
return(-1); }
if((inp=fdopen(ind,"rb"))==NULL) {
close(ind);
errormsg(WHERE,ERR_FDOPEN,str,O_RDONLY);
return(-1); }
setvbuf(inp,NULL,_IOFBF,32*1024);
if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
fclose(inp);
errormsg(WHERE,ERR_OPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
return(-1); }
if((outp=fdopen(outd,"wb"))==NULL) {
close(outd);
fclose(inp);
errormsg(WHERE,ERR_FDOPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
return(-1); }
setvbuf(outp,NULL,_IOFBF,8*1024);
length=filelength(ind);
if(!length) {
fclose(inp);
fclose(outp);
errormsg(WHERE,ERR_LEN,src,0);
return(-1); }
if((buf=(char *)MALLOC(MV_BUFLEN))==NULL) {
fclose(inp);
fclose(outp);
errormsg(WHERE,ERR_ALLOC,nulstr,MV_BUFLEN);
return(-1); }
l=0L;
while(l<length) {
bprintf("%2lu%%",l ? (long)(100.0/((float)length/l)) : 0L);
if(l+chunk>length)
chunk=length-l;
if(fread(buf,1,chunk,inp)!=chunk) {
FREE(buf);
fclose(inp);
fclose(outp);
errormsg(WHERE,ERR_READ,src,chunk);
return(-1); }
if(fwrite(buf,1,chunk,outp)!=chunk) {
FREE(buf);
fclose(inp);
fclose(outp);
errormsg(WHERE,ERR_WRITE,dest,chunk);
return(-1); }
l+=chunk;
bputs("\b\b\b"); }
bputs(" \b\b\b"); /* erase it */
attr(atr);
getftime(ind,&ftime);
setftime(outd,&ftime);
FREE(buf);
fclose(inp);
fclose(outp);
if(!copy && remove(src)) {
errormsg(WHERE,ERR_REMOVE,src,0);
return(-1); }
return(0);
}
/****************************************************************************/
/* Prompts user for System Password. Returns 1 if user entered correct PW */
/****************************************************************************/
char chksyspass(int local)
{
static int inside;
char str[256],str2[256],x,y,atr;
int orgcon=console;
if(inside) return(0);
if(online==ON_REMOTE && !(sys_misc&SM_R_SYSOP))
return(0);
if(online==ON_LOCAL) {
if(!(sys_misc&SM_L_SYSOP))
return(0);
if(!(node_misc&NM_SYSPW) && !(sys_misc&SM_REQ_PW))
return(1); }
if(local) {
x=lclwx();
y=lclwy();
atr=lclatr(LIGHTGRAY<<4);
STATUSLINE;
lclxy(1,node_scrnlen);
lputc(CLREOL);
lputs(" System Password: "); }
else
bputs("SY: ");
console&=~(CON_R_ECHO|CON_L_ECHO);
inside=1;
getstr(str,40,K_UPPER);
if(local) {
TEXTWINDOW;
lclatr(atr);
lclxy(x,y);
statusline(); }
inside=0;
console=orgcon;
if(!local)
CRLF;
if(strcmp(sys_pass,str)) {
sprintf(str2,"%s #%u System password attempt: '%s'"
,useron.alias,useron.number,str);
logline("S!",str2);
return(0); }
return(1);
}
/****************************************************************************/
/* Converts when_t.zone into ASCII format */
/****************************************************************************/
char *zonestr(short zone)
{
static char str[32];
switch((ushort)zone) {
case 0: return("UT");
case AST: return("AST");
case EST: return("EST");
case CST: return("CST");
case MST: return("MST");
case PST: return("PST");
case YST: return("YST");
case HST: return("HST");
case BST: return("BST");
case ADT: return("ADT");
case EDT: return("EDT");
case CDT: return("CDT");
case MDT: return("MDT");
case PDT: return("PDT");
case YDT: return("YDT");
case HDT: return("HDT");
case BDT: return("BDT");
case MID: return("MID");
case VAN: return("VAN");
case EDM: return("EDM");
case WIN: return("WIN");
case BOG: return("BOG");
case CAR: return("CAR");
case RIO: return("RIO");
case FER: return("FER");
case AZO: return("AZO");
case LON: return("LON");
case BER: return("BER");
case ATH: return("ATH");
case MOS: return("MOS");
case DUB: return("DUB");
case KAB: return("KAB");
case KAR: return("KAR");
case BOM: return("BOM");
case KAT: return("KAT");
case DHA: return("DHA");
case BAN: return("BAN");
case HON: return("HON");
case TOK: return("TOK");
case SYD: return("SYD");
case NOU: return("NOU");
case WEL: return("WEL");
}
sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
return(str);
}
/****************************************************************************/
/* Waits so many seconds. Call with 2 or greater. */
/****************************************************************************/
void secwait(int sec)
{
time_t start;
start=time(NULL);
while(time(NULL)-start<sec)
mswait(1);
}
/****************************************************************************/
/* Converts a date string in format MM/DD/YY into unix time format */
/****************************************************************************/
time_t dstrtounix(char *str)
{
if(!strncmp(str,"00/00/00",8))
return(0);
curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
if(str[6]<'7')
date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
else
date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
if(sys_misc&SM_EURODATE) {
date.da_mon=((str[3]&0xf)*10)+(str[4]&0xf);
date.da_day=((str[0]&0xf)*10)+(str[1]&0xf); }
else {
date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
date.da_day=((str[3]&0xf)*10)+(str[4]&0xf); }
return(dostounix(&date,&curtime));
}
/****************************************************************************/
/* Converts unix time format (long - time_t) into a char str MM/DD/YY */
/****************************************************************************/
char *unixtodstr(time_t unix, char *str)
{
if(!unix)
strcpy(str,"00/00/00");
else {
unixtodos(unix,&date,&curtime);
if((unsigned)date.da_mon>12) { /* DOS leap year bug */
date.da_mon=1;
date.da_year++; }
if((unsigned)date.da_day>31)
date.da_day=1;
if(sys_misc&SM_EURODATE)
sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
else
sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
return(str);
}
/****************************************************************************/
/* Checks the disk drive for the existence of a file. Returns 1 if it */
/* exists, 0 if it doesn't. */
/****************************************************************************/
char fexist(char *filespec)
{
struct ffblk f;
if(findfirst(filespec,&f,0 /*FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0)
return(1);
return(0);
}
/****************************************************************************/
/* Returns the length of the file in 'filespec' */
/****************************************************************************/
long flength(char *filespec)
{
struct ffblk f;
if(findfirst(filespec,&f,0)==0)
return(f.ff_fsize);
return(-1L);
}
time_t ftimetounix(struct ftime ft)
{
struct date da;
struct time ti;
ti.ti_min=ft.ft_min;
ti.ti_hour=ft.ft_hour;
ti.ti_hund=0;
ti.ti_sec=ft.ft_tsec*2;
da.da_year=1980+ft.ft_year;
da.da_day=ft.ft_day;
da.da_mon=ft.ft_month;
return(dostounix(&da,&ti));
}
struct ftime unixtoftime(time_t unix)
{
struct date da;
struct time ti;
struct ftime ft;
unixtodos(unix,&da,&ti);
ft.ft_min=ti.ti_min;
ft.ft_hour=ti.ti_hour;
ft.ft_tsec=ti.ti_sec/2;
ft.ft_year=da.da_year-1980;
ft.ft_day=da.da_day;
ft.ft_month=da.da_mon;
return(ft);
}
/****************************************************************************/
/* Returns the time/date of the file in 'filespec' in time_t (unix) format */
/****************************************************************************/
long fdate(char *filespec)
{
int file;
struct ftime f;
time_t t;
if((file=nopen(filespec,O_RDONLY))==-1)
return(0);
getftime(file,&f);
t=ftimetounix(f);
close(file);
return(t);
}
long fdate_dir(char *filespec)
{
struct ffblk f;
struct date fd;
struct time ft;
if(findfirst(filespec,&f,0/* FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0) {
fd.da_day=f.ff_fdate&0x1f;
fd.da_mon=(f.ff_fdate>>5)&0xf;
fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
ft.ti_hour=(f.ff_ftime>>11)&0x1f;
ft.ti_min=(f.ff_ftime>>5)&0x3f;
ft.ti_sec=(f.ff_ftime&0xf)*2;
return(dostounix(&fd,&ft)); }
else return(0);
}
/****************************************************************************/
/* Returns the FidoNet address kept in str as ASCII. */
/****************************************************************************/
faddr_t atofaddr(char *str)
{
char *p;
faddr_t addr;
addr.zone=addr.net=addr.node=addr.point=0;
if((p=strchr(str,':'))!=NULL) {
addr.zone=atoi(str);
addr.net=atoi(p+1); }
else {
if(total_faddrs)
addr.zone=faddr[0].zone;
else
addr.zone=1;
addr.net=atoi(str); }
if(!addr.zone) /* no such thing as zone 0 */
addr.zone=1;
if((p=strchr(str,'/'))!=NULL)
addr.node=atoi(p+1);
else {
if(total_faddrs)
addr.net=faddr[0].net;
else
addr.net=1;
addr.node=atoi(str); }
if((p=strchr(str,'.'))!=NULL)
addr.point=atoi(p+1);
return(addr);
}
/****************************************************************************/
/* Returns an ASCII string for FidoNet address 'addr' */
/****************************************************************************/
char *faddrtoa(faddr_t addr)
{
static char str[25];
char point[25];
sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
if(addr.point) {
sprintf(point,".%u",addr.point);
strcat(str,point); }
return(str);
}
/****************************************************************************/
/* Returns string for 2 digit hex+ numbers up to 575 */
/****************************************************************************/
char *hexplus(uint num, char *str)
{
sprintf(str,"%03x",num);
str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
str[1]=str[2];
str[2]=0;
return(str);
}
uint hptoi(char *str)
{
char tmp[128];
uint i;
if(!str[1] || toupper(str[0])<='F')
return(ahtoul(str));
strcpy(tmp,str);
tmp[0]='F';
i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
return(i);
}
#ifndef __FLAT__
void beep(int freq, int dur)
{
sound(freq);
mswait(dur);
nosound();
}
int kbd_state(void)
{
return(peekb(0,0x417)); /* Check scroll lock */
}
#elif defined(__WIN32__)
void beep(int freq, int dur)
{
Beep(freq,dur); // Requires WINDOWS.H
}
void mswait(int ms)
{
Sleep(ms); // Requires WINDOWS.H
}
#endif
#ifdef __OS2__
int kbd_state(void)
{
KBDINFO info;
KbdGetStatus(&info,0);
return(info.fsState);
}
void mswait(int msec)
{
DosSleep(msec ? msec : 1);
}
#elif defined(__WIN32__)
#define KBDSTF_RIGHTSHIFT 0x0001
#define KBDSTF_LEFTSHIFT 0x0002
#define KBDSTF_CONTROL 0x0004
#define KBDSTF_ALT 0x0008
#define KBDSTF_SCROLLLOCK_ON 0x0010
#define KBDSTF_NUMLOCK_ON 0x0020
#define KBDSTF_CAPSLOCK_ON 0x0040
#define KBDSTF_INSERT_ON 0x0080
#define KBDSTF_LEFTCONTROL 0x0100
#define KBDSTF_LEFTALT 0x0200
#define KBDSTF_RIGHTCONTROL 0x0400
#define KBDSTF_RIGHTALT 0x0800
#define KBDSTF_SCROLLLOCK 0x1000
#define KBDSTF_NUMLOCK 0x2000
#define KBDSTF_CAPSLOCK 0x4000
#define KBDSTF_SYSREQ 0x8000
int kbd_state(void)
{
int i=0;
ulong l;
INPUT_RECORD rec;
PeekConsoleInput(stdin,&rec,1,&l);
if(rec.EventType==KEY_EVENT)
l=rec.Event.KeyEvent.dwControlKeyState;
else if(rec.EventType==MOUSE_EVENT)
l=rec.Event.MouseEvent.dwControlKeyState;
else
return(0);
/* Translate Win32 key state to IBM key state */
if(l&RIGHT_ALT_PRESSED)
i|=KBDSTF_RIGHTALT;
if(l&LEFT_ALT_PRESSED)
i|=KBDSTF_LEFTALT;
if(l&RIGHT_CTRL_PRESSED)
i|=KBDSTF_RIGHTCONTROL;
if(l&LEFT_CTRL_PRESSED)
i|=KBDSTF_LEFTCONTROL;
if(l&CAPSLOCK_ON)
i|=KBDSTF_CAPSLOCK;
if(l&NUMLOCK_ON)
i|=KBDSTF_NUMLOCK;
if(l&SCROLLLOCK_ON)
i|=KBDSTF_SCROLLLOCK;
if(l&SHIFT_PRESSED)
i|=KBDSTF_LEFTSHIFT;
return(i);
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.