home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / MISC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-24  |  21.4 KB  |  816 lines

  1. #line 1 "MISC.C"
  2.  
  3. /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
  4.  
  5. /***************************************************************************/
  6. /* Miscellaneous functions that are useful many places throughout the code */
  7. /***************************************************************************/
  8.  
  9. #include "sbbs.h"
  10. #include "crc32.h"
  11.  
  12. #ifdef __WIN32__
  13. #include <windows.h>    // Required for kbd_state(), beep(), and mswait()
  14. #endif
  15.  
  16. /****************************************************************************/
  17. /* Returns the number of characters in 'str' not counting ctrl-ax codes        */
  18. /* or the null terminator                                                    */
  19. /****************************************************************************/
  20. int bstrlen(char *str)
  21. {
  22.     int i=0;
  23.  
  24. while(*str) {
  25.     if(*str==1) /* ctrl-a */
  26.         str++;
  27.     else
  28.         i++;
  29.     if(!(*str)) break;
  30.     str++; }
  31. return(i);
  32. }
  33.  
  34. void strip_ctrl(char *str)
  35. {
  36.     char tmp[1024];
  37.     int i,j,k;
  38.  
  39. k=strlen(str);
  40. for(i=j=0;i<k;i++)
  41.     if(str[i]==1)  /* Ctrl-a */
  42.         i++;
  43.     else if(j && str[i]<=SP && tmp[j-1]==SP)
  44.         continue;
  45.     else if(i && !isalnum(str[i]) && str[i]==str[i-1])
  46.         continue;
  47.     else if((uchar)str[i]>=SP)
  48.         tmp[j++]=str[i];
  49.     else if(str[i]==TAB || (str[i]==CR && str[i+1]==LF))
  50.         tmp[j++]=SP;
  51. tmp[j]=0;
  52. strcpy(str,tmp);
  53. }
  54.  
  55. void strip_exascii(char *str)
  56. {
  57.     char tmp[1024];
  58.     int i,j,k;
  59.  
  60. k=strlen(str);
  61. for(i=j=0;i<k;i++)
  62.     if(!(str[i]&0x80))
  63.         tmp[j++]=str[i];
  64. tmp[j]=0;
  65. strcpy(str,tmp);
  66. }
  67.  
  68. /****************************************************************************/
  69. /* Returns in 'string' a character representation of the number in l with   */
  70. /* commas.                                                                    */
  71. /****************************************************************************/
  72. char *ultoac(ulong l, char *string)
  73. {
  74.     char str[256];
  75.     char i,j,k;
  76.  
  77. ultoa(l,str,10);
  78. i=strlen(str)-1;
  79. j=i/3+1+i;
  80. string[j--]=0;
  81. for(k=1;i>-1;k++) {
  82.     string[j--]=str[i--];
  83.     if(j>0 && !(k%3))
  84.         string[j--]=','; }
  85. return(string);
  86. }
  87.  
  88. /****************************************************************************/
  89. /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN    */
  90. /* number of times if the attempted file is already open or denying access  */
  91. /* for some other reason.    All files are opened in BINARY mode.            */
  92. /****************************************************************************/
  93. int nopen(char *str, int access)
  94. {
  95.     char logstr[256];
  96.     int file,share,count=0;
  97.  
  98. if(access&O_DENYNONE) {
  99.     share=SH_DENYNO;
  100.     access&=~O_DENYNONE; }
  101. else if(access==O_RDONLY) share=SH_DENYWR;
  102. else share=SH_DENYRW;
  103. while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1)
  104.     && errno==EACCES && count++<LOOP_NOPEN)
  105.     if(count>10)
  106.         mswait(55);
  107. if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN) {
  108.     sprintf(logstr,"NOPEN COLLISION - File: %s Count: %d"
  109.         ,str,count);
  110.     logline("!!",logstr); }
  111. if(file==-1 && errno==EACCES)
  112.     bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7");
  113. return(file);
  114. }
  115.  
  116. /****************************************************************************/
  117. /* This function performs an nopen, but returns a file stream with a buffer */
  118. /* allocated.                                                                */
  119. /****************************************************************************/
  120. FILE *fnopen(int *file, char *str, int access)
  121. {
  122.     char mode[128];
  123.     FILE *stream;
  124.  
  125. if(((*file)=nopen(str,access))==-1)
  126.     return(NULL);
  127.  
  128. if(access&O_APPEND) {
  129.     if(access&O_RDONLY)
  130.         strcpy(mode,"a+");
  131.     else
  132.         strcpy(mode,"a"); }
  133. else {
  134.     if(access&O_WRONLY)
  135.         strcpy(mode,"r+");
  136.     else
  137.         strcpy(mode,"r"); }
  138. stream=fdopen((*file),mode);
  139. if(stream==NULL) {
  140.     close(*file);
  141.     errormsg(WHERE,ERR_FDOPEN,str,access);
  142.     return(NULL); }
  143. setvbuf(stream,NULL,_IOFBF,2*1024);
  144. return(stream);
  145. }
  146.  
  147. #ifndef __FLAT__
  148. /****************************************************************************/
  149. /* This function reads files that are potentially larger than 32k.          */
  150. /* Up to one megabyte of data can be read with each call.                   */
  151. /****************************************************************************/
  152. long lread(int file, char huge *buf,long bytes)
  153. {
  154.     long count;
  155.  
  156. for(count=bytes;count>32767;count-=32767,buf+=32767)
  157.     if(read(file,(char *)buf,32767)!=32767)
  158.         return(-1L);
  159. if(read(file,(char *)buf,(int)count)!=count)
  160.     return(-1L);
  161. return(bytes);
  162. }
  163.  
  164. long lfread(char huge *buf, long bytes, FILE *fp)
  165. {
  166.     long count;
  167.  
  168. for(count=bytes;count>0x7fff;count-=0x7fff,buf+=0x7fff)
  169.     if(fread((char *)buf,1,0x7fff,fp)!=0x7fff)
  170.         return(0);
  171. if(fread((char *)buf,1,(int)count,fp)!=count)
  172.     return(0);
  173. return(bytes);
  174. }
  175.  
  176. /****************************************************************************/
  177. /* This function writes files that are potentially larger than 32767 bytes  */
  178. /* Up to one megabytes of data can be written with each call.                */
  179. /****************************************************************************/
  180. long lwrite(int file, char huge *buf, long bytes)
  181. {
  182.  
  183.     long count;
  184.  
  185. for(count=bytes;count>32767;count-=32767,buf+=32767)
  186.     if(write(file,(char *)buf,32767)!=32767)
  187.         return(-1L);
  188. if(write(file,(char *)buf,(int)count)!=count)
  189.     return(-1L);
  190. return(bytes);
  191. }
  192. #endif
  193.  
  194. /****************************************************************************/
  195. /* Truncates white-space chars off end of 'str' and terminates at first tab */
  196. /****************************************************************************/
  197. void truncsp(char *str)
  198. {
  199.     uint c;
  200.  
  201. str[strcspn(str,"\t")]=0;
  202. c=strlen(str);
  203. while(c && (uchar)str[c-1]<=SP) c--;
  204. str[c]=0;
  205. }
  206.  
  207. /****************************************************************************/
  208. /* Puts a backslash on path strings                                         */
  209. /****************************************************************************/
  210. void backslash(char *str)
  211. {
  212.     int i;
  213.  
  214. i=strlen(str);
  215. if(i && str[i-1]!='\\') {
  216.     str[i]='\\'; str[i+1]=0; }
  217. }
  218.  
  219. /****************************************************************************/
  220. /* Puts a backslash on path strings if not just a drive letter and colon    */
  221. /****************************************************************************/
  222. void backslashcolon(char *str)
  223. {
  224.     int i;
  225.  
  226. i=strlen(str);
  227. if(i && str[i-1]!='\\' && str[i-1]!=':') {
  228.     str[i]='\\'; str[i+1]=0; }
  229. }
  230.  
  231. /****************************************************************************/
  232. /* Updates 16-bit "rcrc" with character 'ch'                                */
  233. /****************************************************************************/
  234. void ucrc16(uchar ch, ushort *rcrc) {
  235.     ushort i, cy;
  236.     uchar nch=ch;
  237.  
  238. for (i=0; i<8; i++) {
  239.     cy=*rcrc & 0x8000;
  240.     *rcrc<<=1;
  241.     if (nch & 0x80) *rcrc |= 1;
  242.     nch<<=1;
  243.     if (cy) *rcrc ^= 0x1021; }
  244. }
  245.  
  246. /****************************************************************************/
  247. /* Returns CRC-16 of string (not including terminating NULL)                */
  248. /****************************************************************************/
  249. ushort crc16(char *str)
  250. {
  251.     int     i=0;
  252.     ushort    crc=0;
  253.  
  254. ucrc16(0,&crc);
  255. while(str[i])
  256.     ucrc16(str[i++],&crc);
  257. ucrc16(0,&crc);
  258. ucrc16(0,&crc);
  259. return(crc);
  260. }
  261.  
  262. /****************************************************************************/
  263. /* Returns CRC-32 of string (not including terminating NULL)                */
  264. /****************************************************************************/
  265. ulong crc32(char *buf, ulong len)
  266. {
  267.     ulong l,crc=0xffffffff;
  268.  
  269. for(l=0;l<len;l++)
  270.     crc=ucrc32(buf[l],crc);
  271. return(~crc);
  272. }
  273.  
  274. /****************************************************************************/
  275. /* Compares pointers to pointers to char. Used in conjuction with qsort()   */
  276. /****************************************************************************/
  277. int pstrcmp(char **str1, char **str2)
  278. {
  279. return(strcmp(*str1,*str2));
  280. }
  281.  
  282. /****************************************************************************/
  283. /* Returns the number of characters that are the same between str1 and str2 */
  284. /****************************************************************************/
  285. int strsame(char *str1, char *str2)
  286. {
  287.     int i,j=0;
  288.  
  289. for(i=0;i<strlen(str1);i++)
  290.     if(str1[i]==str2[i]) j++;
  291. return(j);
  292. }
  293.  
  294. #define MV_BUFLEN    4096
  295.  
  296. /****************************************************************************/
  297. /* Moves or copies a file from one dir to another                           */
  298. /* both 'src' and 'dest' must contain full path and filename                */
  299. /* returns 0 if successful, -1 if error                                     */
  300. /****************************************************************************/
  301. int mv(char *src, char *dest, char copy)
  302. {
  303.     char str[256],*buf,atr=curatr;
  304.     int  ind,outd;
  305.     long length,chunk=MV_BUFLEN,l;
  306.     struct ftime ftime;
  307.     FILE *inp,*outp;
  308.  
  309. if(!stricmp(src,dest))     /* source and destination are the same! */
  310.     return(0);
  311. if(!fexist(src)) {
  312.     bprintf("\r\n\7MV ERROR: Source doesn't exist\r\n'%s'\r\n"
  313.         ,src);
  314.     return(-1); }
  315. if(!copy && fexist(dest)) {
  316.     bprintf("\r\n\7MV ERROR: Destination already exists\r\n'%s'\r\n"
  317.         ,dest);
  318.     return(-1); }
  319. if(!copy && ((src[1]!=':' && dest[1]!=':')
  320.     || (src[1]==':' && dest[1]==':' && toupper(src[0])==toupper(dest[0])))) {
  321.     if(rename(src,dest)) {                        /* same drive, so move */
  322.         bprintf("\r\nMV ERROR: Error renaming '%s'"
  323.                 "\r\n                      to '%s'\r\n\7",src,dest);
  324.         return(-1); }
  325.     return(0); }
  326. attr(WHITE);
  327. if((ind=nopen(src,O_RDONLY))==-1) {
  328.     errormsg(WHERE,ERR_OPEN,src,O_RDONLY);
  329.     return(-1); }
  330. if((inp=fdopen(ind,"rb"))==NULL) {
  331.     close(ind);
  332.     errormsg(WHERE,ERR_FDOPEN,str,O_RDONLY);
  333.     return(-1); }
  334. setvbuf(inp,NULL,_IOFBF,32*1024);
  335. if((outd=nopen(dest,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  336.     fclose(inp);
  337.     errormsg(WHERE,ERR_OPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
  338.     return(-1); }
  339. if((outp=fdopen(outd,"wb"))==NULL) {
  340.     close(outd);
  341.     fclose(inp);
  342.     errormsg(WHERE,ERR_FDOPEN,dest,O_WRONLY|O_CREAT|O_TRUNC);
  343.     return(-1); }
  344. setvbuf(outp,NULL,_IOFBF,8*1024);
  345. length=filelength(ind);
  346. if(!length) {
  347.     fclose(inp);
  348.     fclose(outp);
  349.     errormsg(WHERE,ERR_LEN,src,0);
  350.     return(-1); }
  351. if((buf=(char *)MALLOC(MV_BUFLEN))==NULL) {
  352.     fclose(inp);
  353.     fclose(outp);
  354.     errormsg(WHERE,ERR_ALLOC,nulstr,MV_BUFLEN);
  355.     return(-1); }
  356. l=0L;
  357. while(l<length) {
  358.     bprintf("%2lu%%",l ? (long)(100.0/((float)length/l)) : 0L);
  359.     if(l+chunk>length)
  360.         chunk=length-l;
  361.     if(fread(buf,1,chunk,inp)!=chunk) {
  362.         FREE(buf);
  363.         fclose(inp);
  364.         fclose(outp);
  365.         errormsg(WHERE,ERR_READ,src,chunk);
  366.         return(-1); }
  367.     if(fwrite(buf,1,chunk,outp)!=chunk) {
  368.         FREE(buf);
  369.         fclose(inp);
  370.         fclose(outp);
  371.         errormsg(WHERE,ERR_WRITE,dest,chunk);
  372.         return(-1); }
  373.     l+=chunk;
  374.     bputs("\b\b\b"); }
  375. bputs("   \b\b\b");  /* erase it */
  376. attr(atr);
  377. getftime(ind,&ftime);
  378. setftime(outd,&ftime);
  379. FREE(buf);
  380. fclose(inp);
  381. fclose(outp);
  382. if(!copy && remove(src)) {
  383.     errormsg(WHERE,ERR_REMOVE,src,0);
  384.     return(-1); }
  385. return(0);
  386. }
  387.  
  388. /****************************************************************************/
  389. /* Prompts user for System Password. Returns 1 if user entered correct PW    */
  390. /****************************************************************************/
  391. char chksyspass(int local)
  392. {
  393.     static    int inside;
  394.     char    str[256],str2[256],x,y,atr;
  395.     int     orgcon=console;
  396.  
  397. if(inside) return(0);
  398. if(online==ON_REMOTE && !(sys_misc&SM_R_SYSOP))
  399.     return(0);
  400. if(online==ON_LOCAL) {
  401.     if(!(sys_misc&SM_L_SYSOP))
  402.         return(0);
  403.     if(!(node_misc&NM_SYSPW) && !(sys_misc&SM_REQ_PW))
  404.         return(1); }
  405. if(local) {
  406.     x=lclwx();
  407.     y=lclwy();
  408.     atr=lclatr(LIGHTGRAY<<4);
  409.     STATUSLINE;
  410.     lclxy(1,node_scrnlen);
  411.     lputc(CLREOL);
  412.     lputs("  System Password: "); }
  413. else
  414.     bputs("SY: ");
  415. console&=~(CON_R_ECHO|CON_L_ECHO);
  416. inside=1;
  417. getstr(str,40,K_UPPER);
  418. if(local) {
  419.     TEXTWINDOW;
  420.     lclatr(atr);
  421.     lclxy(x,y);
  422.     statusline(); }
  423. inside=0;
  424. console=orgcon;
  425. if(!local)
  426.     CRLF;
  427. if(strcmp(sys_pass,str)) {
  428.     sprintf(str2,"%s #%u System password attempt: '%s'"
  429.         ,useron.alias,useron.number,str);
  430.     logline("S!",str2);
  431.     return(0); }
  432. return(1);
  433. }
  434.  
  435. /****************************************************************************/
  436. /* Converts when_t.zone into ASCII format                                   */
  437. /****************************************************************************/
  438. char *zonestr(short zone)
  439. {
  440.     static char str[32];
  441.  
  442. switch((ushort)zone) {
  443.     case 0:     return("UT");
  444.     case AST:   return("AST");
  445.     case EST:   return("EST");
  446.     case CST:   return("CST");
  447.     case MST:   return("MST");
  448.     case PST:   return("PST");
  449.     case YST:   return("YST");
  450.     case HST:   return("HST");
  451.     case BST:   return("BST");
  452.     case ADT:   return("ADT");
  453.     case EDT:   return("EDT");
  454.     case CDT:   return("CDT");
  455.     case MDT:   return("MDT");
  456.     case PDT:   return("PDT");
  457.     case YDT:   return("YDT");
  458.     case HDT:   return("HDT");
  459.     case BDT:   return("BDT");
  460.     case MID:   return("MID");
  461.     case VAN:   return("VAN");
  462.     case EDM:   return("EDM");
  463.     case WIN:   return("WIN");
  464.     case BOG:   return("BOG");
  465.     case CAR:   return("CAR");
  466.     case RIO:   return("RIO");
  467.     case FER:   return("FER");
  468.     case AZO:   return("AZO");
  469.     case LON:   return("LON");
  470.     case BER:   return("BER");
  471.     case ATH:   return("ATH");
  472.     case MOS:   return("MOS");
  473.     case DUB:   return("DUB");
  474.     case KAB:   return("KAB");
  475.     case KAR:   return("KAR");
  476.     case BOM:   return("BOM");
  477.     case KAT:   return("KAT");
  478.     case DHA:   return("DHA");
  479.     case BAN:   return("BAN");
  480.     case HON:   return("HON");
  481.     case TOK:   return("TOK");
  482.     case SYD:   return("SYD");
  483.     case NOU:   return("NOU");
  484.     case WEL:   return("WEL");
  485.     }
  486.  
  487. sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
  488. return(str);
  489. }
  490.  
  491. /****************************************************************************/
  492. /* Waits so many seconds. Call with 2 or greater.                            */
  493. /****************************************************************************/
  494. void secwait(int sec)
  495. {
  496.     time_t start;
  497.  
  498. start=time(NULL);
  499. while(time(NULL)-start<sec)
  500.     mswait(1);
  501. }
  502.  
  503. /****************************************************************************/
  504. /* Converts a date string in format MM/DD/YY into unix time format            */
  505. /****************************************************************************/
  506. time_t dstrtounix(char *str)
  507. {
  508.  
  509. if(!strncmp(str,"00/00/00",8))
  510.     return(0);
  511. curtime.ti_hour=curtime.ti_min=curtime.ti_sec=0;
  512. if(str[6]<'7')
  513.     date.da_year=2000+((str[6]&0xf)*10)+(str[7]&0xf);
  514. else
  515.     date.da_year=1900+((str[6]&0xf)*10)+(str[7]&0xf);
  516. if(sys_misc&SM_EURODATE) {
  517.     date.da_mon=((str[3]&0xf)*10)+(str[4]&0xf);
  518.     date.da_day=((str[0]&0xf)*10)+(str[1]&0xf); }
  519. else {
  520.     date.da_mon=((str[0]&0xf)*10)+(str[1]&0xf);
  521.     date.da_day=((str[3]&0xf)*10)+(str[4]&0xf); }
  522. return(dostounix(&date,&curtime));
  523. }
  524.  
  525. /****************************************************************************/
  526. /* Converts unix time format (long - time_t) into a char str MM/DD/YY        */
  527. /****************************************************************************/
  528. char *unixtodstr(time_t unix, char *str)
  529. {
  530.  
  531. if(!unix)
  532.     strcpy(str,"00/00/00");
  533. else {
  534.     unixtodos(unix,&date,&curtime);
  535.     if((unsigned)date.da_mon>12) {      /* DOS leap year bug */
  536.         date.da_mon=1;
  537.         date.da_year++; }
  538.     if((unsigned)date.da_day>31)
  539.         date.da_day=1;
  540.     if(sys_misc&SM_EURODATE)
  541.         sprintf(str,"%02u/%02u/%02u",date.da_day,date.da_mon
  542.             ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900);
  543.     else
  544.         sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
  545.             ,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
  546. return(str);
  547. }
  548.  
  549. /****************************************************************************/
  550. /* Checks the disk drive for the existence of a file. Returns 1 if it       */
  551. /* exists, 0 if it doesn't.                                                 */
  552. /****************************************************************************/
  553. char fexist(char *filespec)
  554. {
  555.     struct ffblk f;
  556.  
  557. if(findfirst(filespec,&f,0 /*FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0)
  558.     return(1);
  559. return(0);
  560. }
  561.  
  562. /****************************************************************************/
  563. /* Returns the length of the file in 'filespec'                             */
  564. /****************************************************************************/
  565. long flength(char *filespec)
  566. {
  567.     struct ffblk f;
  568.  
  569. if(findfirst(filespec,&f,0)==0)
  570.     return(f.ff_fsize);
  571. return(-1L);
  572. }
  573.  
  574. time_t ftimetounix(struct ftime ft)
  575. {
  576.     struct date da;
  577.     struct time ti;
  578.  
  579. ti.ti_min=ft.ft_min;
  580. ti.ti_hour=ft.ft_hour;
  581. ti.ti_hund=0;
  582. ti.ti_sec=ft.ft_tsec*2;
  583. da.da_year=1980+ft.ft_year;
  584. da.da_day=ft.ft_day;
  585. da.da_mon=ft.ft_month;
  586. return(dostounix(&da,&ti));
  587. }
  588.  
  589. struct ftime unixtoftime(time_t unix)
  590. {
  591.     struct date da;
  592.     struct time ti;
  593.     struct ftime ft;
  594.  
  595. unixtodos(unix,&da,&ti);
  596. ft.ft_min=ti.ti_min;
  597. ft.ft_hour=ti.ti_hour;
  598. ft.ft_tsec=ti.ti_sec/2;
  599. ft.ft_year=da.da_year-1980;
  600. ft.ft_day=da.da_day;
  601. ft.ft_month=da.da_mon;
  602. return(ft);
  603. }
  604.  
  605. /****************************************************************************/
  606. /* Returns the time/date of the file in 'filespec' in time_t (unix) format  */
  607. /****************************************************************************/
  608. long fdate(char *filespec)
  609. {
  610.     int file;
  611.     struct ftime f;
  612.     time_t t;
  613.  
  614. if((file=nopen(filespec,O_RDONLY))==-1)
  615.     return(0);
  616. getftime(file,&f);
  617. t=ftimetounix(f);
  618. close(file);
  619. return(t);
  620. }
  621.  
  622. long fdate_dir(char *filespec)
  623. {
  624.     struct ffblk f;
  625.     struct date fd;
  626.     struct time ft;
  627.  
  628. if(findfirst(filespec,&f,0/* FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC */)==0) {
  629.     fd.da_day=f.ff_fdate&0x1f;
  630.     fd.da_mon=(f.ff_fdate>>5)&0xf;
  631.     fd.da_year=1980+((f.ff_fdate>>9)&0x7f);
  632.     ft.ti_hour=(f.ff_ftime>>11)&0x1f;
  633.     ft.ti_min=(f.ff_ftime>>5)&0x3f;
  634.     ft.ti_sec=(f.ff_ftime&0xf)*2;
  635.     return(dostounix(&fd,&ft)); }
  636. else return(0);
  637. }
  638.  
  639.  
  640.  
  641. /****************************************************************************/
  642. /* Returns the FidoNet address kept in str as ASCII.                        */
  643. /****************************************************************************/
  644. faddr_t atofaddr(char *str)
  645. {
  646.     char *p;
  647.     faddr_t addr;
  648.  
  649. addr.zone=addr.net=addr.node=addr.point=0;
  650. if((p=strchr(str,':'))!=NULL) {
  651.     addr.zone=atoi(str);
  652.     addr.net=atoi(p+1); }
  653. else {
  654.     if(total_faddrs)
  655.         addr.zone=faddr[0].zone;
  656.     else
  657.         addr.zone=1;
  658.     addr.net=atoi(str); }
  659. if(!addr.zone)              /* no such thing as zone 0 */
  660.     addr.zone=1;
  661. if((p=strchr(str,'/'))!=NULL)
  662.     addr.node=atoi(p+1);
  663. else {
  664.     if(total_faddrs)
  665.         addr.net=faddr[0].net;
  666.     else
  667.         addr.net=1;
  668.     addr.node=atoi(str); }
  669. if((p=strchr(str,'.'))!=NULL)
  670.     addr.point=atoi(p+1);
  671. return(addr);
  672. }
  673.  
  674. /****************************************************************************/
  675. /* Returns an ASCII string for FidoNet address 'addr'                       */
  676. /****************************************************************************/
  677. char *faddrtoa(faddr_t addr)
  678. {
  679.     static char str[25];
  680.     char point[25];
  681.  
  682. sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
  683. if(addr.point) {
  684.     sprintf(point,".%u",addr.point);
  685.     strcat(str,point); }
  686. return(str);
  687. }
  688.  
  689. /****************************************************************************/
  690. /* Returns string for 2 digit hex+ numbers up to 575                        */
  691. /****************************************************************************/
  692. char *hexplus(uint num, char *str)
  693. {
  694. sprintf(str,"%03x",num);
  695. str[0]=num/0x100 ? 'f'+(num/0x10)-0xf : str[1];
  696. str[1]=str[2];
  697. str[2]=0;
  698. return(str);
  699. }
  700.  
  701. uint hptoi(char *str)
  702. {
  703.     char tmp[128];
  704.     uint i;
  705.  
  706. if(!str[1] || toupper(str[0])<='F')
  707.     return(ahtoul(str));
  708. strcpy(tmp,str);
  709. tmp[0]='F';
  710. i=ahtoul(tmp)+((toupper(str[0])-'F')*0x10);
  711. return(i);
  712. }
  713.  
  714. #ifndef __FLAT__
  715.  
  716. void beep(int freq, int dur)
  717. {
  718. sound(freq);
  719. mswait(dur);
  720. nosound();
  721. }
  722.  
  723. int kbd_state(void)
  724. {
  725. return(peekb(0,0x417));      /* Check scroll lock */
  726. }
  727.  
  728. #elif defined(__WIN32__)
  729.  
  730. void beep(int freq, int dur)
  731. {
  732. Beep(freq,dur);                 // Requires WINDOWS.H
  733. }
  734.  
  735. void mswait(int ms)
  736. {
  737. Sleep(ms);                        // Requires WINDOWS.H
  738. }
  739.  
  740. #endif
  741.  
  742. #ifdef __OS2__
  743.  
  744. int kbd_state(void)
  745. {
  746.     KBDINFO info;
  747.  
  748. KbdGetStatus(&info,0);
  749. return(info.fsState);
  750. }
  751.  
  752. void mswait(int msec)
  753. {
  754. DosSleep(msec ? msec : 1);
  755. }
  756.  
  757. #elif defined(__WIN32__)
  758.  
  759. #define KBDSTF_RIGHTSHIFT                0x0001
  760. #define KBDSTF_LEFTSHIFT                0x0002
  761. #define KBDSTF_CONTROL                    0x0004
  762. #define KBDSTF_ALT                        0x0008
  763. #define KBDSTF_SCROLLLOCK_ON            0x0010
  764. #define KBDSTF_NUMLOCK_ON                0x0020
  765. #define KBDSTF_CAPSLOCK_ON                0x0040
  766. #define KBDSTF_INSERT_ON                0x0080
  767. #define KBDSTF_LEFTCONTROL                0x0100
  768. #define KBDSTF_LEFTALT                    0x0200
  769. #define KBDSTF_RIGHTCONTROL             0x0400
  770. #define KBDSTF_RIGHTALT                 0x0800
  771. #define KBDSTF_SCROLLLOCK                0x1000
  772. #define KBDSTF_NUMLOCK                    0x2000
  773. #define KBDSTF_CAPSLOCK                 0x4000
  774. #define KBDSTF_SYSREQ                    0x8000
  775.  
  776. int kbd_state(void)
  777. {
  778.     int i=0;
  779.     ulong l;
  780.     INPUT_RECORD rec;
  781.  
  782. PeekConsoleInput(stdin,&rec,1,&l);
  783. if(rec.EventType==KEY_EVENT)
  784.     l=rec.Event.KeyEvent.dwControlKeyState;
  785. else if(rec.EventType==MOUSE_EVENT)
  786.     l=rec.Event.MouseEvent.dwControlKeyState;
  787. else
  788.     return(0);
  789.  
  790. /* Translate Win32 key state to IBM key state */
  791.  
  792. if(l&RIGHT_ALT_PRESSED)
  793.     i|=KBDSTF_RIGHTALT;
  794. if(l&LEFT_ALT_PRESSED)
  795.     i|=KBDSTF_LEFTALT;
  796. if(l&RIGHT_CTRL_PRESSED)
  797.     i|=KBDSTF_RIGHTCONTROL;
  798. if(l&LEFT_CTRL_PRESSED)
  799.     i|=KBDSTF_LEFTCONTROL;
  800. if(l&CAPSLOCK_ON)
  801.     i|=KBDSTF_CAPSLOCK;
  802. if(l&NUMLOCK_ON)
  803.     i|=KBDSTF_NUMLOCK;
  804. if(l&SCROLLLOCK_ON)
  805.     i|=KBDSTF_SCROLLLOCK;
  806. if(l&SHIFT_PRESSED)
  807.     i|=KBDSTF_LEFTSHIFT;
  808.  
  809. return(i);
  810. }
  811.  
  812.  
  813.  
  814. #endif
  815.  
  816.