|
|
1.1 ! root 1: /* XSDK.C */ ! 2: ! 3: /****************************************************************************/ ! 4: /* Synchronet External Program Software Development Kit */ ! 5: /* 1995 Digital Dynamics */ ! 6: /****************************************************************************/ ! 7: ! 8: /****************************************************************************/ ! 9: /* This source code file is public domain and may be modified, compiled */ ! 10: /* distributed, or used in any way, in part or whole for any purposes */ ! 11: /* without the consent or notification of Digital Dynamics. */ ! 12: /* */ ! 13: /* We only request that you display to the user, at some point, in your */ ! 14: /* program the character "XSDK" and the version number. */ ! 15: /* example: bprintf("XSDK v%s",xsdk_ver); */ ! 16: /****************************************************************************/ ! 17: ! 18: /****************************************************************************/ ! 19: /* The source code for two external programs developed by Digital Dynamics */ ! 20: /* using XSDK (Synchronet Blackjack [SBJ] and Synchronet BBS List [SBL]) */ ! 21: /* are available to the public domain as examples of how to implement the */ ! 22: /* functions and variables included in this software development kit. */ ! 23: /****************************************************************************/ ! 24: ! 25: /****************************************************/ ! 26: /* For use with Borland/Turbo C and C++ compilers. */ ! 27: /* Tabstop set to 4. */ ! 28: /****************************************************/ ! 29: ! 30: /***************************** Revision History *****************************\ ! 31: ! 32: Initial version for use with Synchronet v1a r6 ! 33: 1.0� ! 34: Added bgotoxy() macro ! 35: Added mnehigh and mnelow vars for control of the mnemonic colors ! 36: Added sys_nodes and node_num variables to xtrn_sdk.c ! 37: Added MAX_NODES to xtrn_sdk.h ! 38: Added printfile() function to xtrn_sdk.c ! 39: Added rputs() (Raw put string) ! 40: Added getstr() (Get string) ! 41: Added redrwstr() (Redraw string) ! 42: Added stripattr() (String attributes) ! 43: Added sys_op var and the reading from the xtrn.dat ! 44: Removed user_min and the reading from the xtrn.dat ! 45: Changed read_xtrn_dat() to initdata() ! 46: Added ctrl-break handler to xtrn_sdk ! 47: Changed xtrn.dat format (again), adding system operator, ! 48: guru name, user ml, tl, birthdate and sex. ! 49: Added username() function ! 50: Renamed xtrn_sdk.* to xsdk.* and xtrnvars.c to xsdkvars.c ! 51: and xtrndefs.h to xsdkdefs.h ! 52: Added fexist() function ! 53: 1.0 ! 54: Ctrl-p is now switched into ctrl-^ by SBBS ! 55: Fixed relative data_dir bug in username() ! 56: 1.01 ! 57: Added flength() function and lowered disk activity ! 58: Lowered MAX_CARDS from 20 to 10 and made the re-shuffling happen ! 59: less often. ! 60: 1.02 ! 61: Fixed bug in attr() for monochrome users ! 62: 1.03 ! 63: Made warning and timeout times variables (sec_warn and sec_timeout) ! 64: Added SYSOP macro ! 65: Made it so sysop won't get timeout ! 66: Added user's phone number to XTRN.DAT ! 67: Added modem and com port information to XTRN.DAT ! 68: Added ahtoul function ! 69: Changed getstr commands Ctrl-L to Ctrl-R and Ctrl-P to Ctrl-\ ! 70: 1.04 ! 71: Added intercommunication between the external programs and users ! 72: on the BBS or other external programs written with XSDK. ! 73: Added rprintf() function ! 74: Made many changes to getstr() function ! 75: 2.00 ! 76: Added DESQview awareness ! 77: Removed difftime() function calls completely ! 78: Added ungetkey() function ! 79: Added memory address of last modem status register for com routines ! 80: so we can track DCD incase user hangs up. ! 81: Added checkline function that does the checking of DCD. ! 82: Added new bug-free fdelay() routine to replace TC's delay() that ! 83: crashes multi-taskers such as DESQview and Windows ! 84: 2.01 ! 85: Added external program name access for user listings. ! 86: Added last node to send message to remembering and defaulting. ! 87: Added MALLOC and FREE macros for memory model non-specific memory ! 88: allocation. ! 89: 2.02 ! 90: Added INTRSBBS.DAT support for Synchronet shrinking to run programs ! 91: written with XSDK (new with v1b rev 01). ! 92: Added user's main flags, transfer flags, exemptions, and ! 93: restrictions to XTRN.DAT ! 94: Added support for the NODE_PAGE action (paging for private chat) ! 95: when listing nodes (printnodedat()). ! 96: Added user expiration date support to XTRN.DAT ! 97: 2.03 ! 98: Fixed bug with com_base variable being messed up. ! 99: New messaging system supported (for v1b r2 and higher) ! 100: (putnmsg and getnmsg functions). ! 101: 2.10 ! 102: Added support for file retrieving node status display. ! 103: NOPEN collision notice only appears after 25 retries. ! 104: 2.11 ! 105: Changed getnmsg function to not use IXB files. ! 106: Changed getsmsg function to not re-open for truncate. ! 107: Added user address, location, and zip/postal code suppport. ! 108: Added support for local arrow keys, home, end, ins, and del. ! 109: Remote keys ^] (back one space) and ^BkSpc (del) supported now. ! 110: Added support for high-bit Ctrl-A codes (for cursor positioning) ! 111: Removed file locking check - slowed down initialization sometimes. ! 112: Change user_ml to user_level, removed user_tl, changed user_mf to ! 113: user_flags1, changed user_tf to user_flags2, and added ! 114: user_flags3 and user_flags4. ! 115: cls() now updates lncntr like it should have. ! 116: Added ctrl-break handler so that users can abort printfile() ! 117: If a ctrl-c is received by inkey, the aborted flag is set. ! 118: Removed fdelay from XSDK and replaced with mswait for better ! 119: multitasker performance ! 120: 2.20 ! 121: New mswait that support OS2/Windows, DOS Idle, and non-DV modes. ! 122: XTRN.DAT passes mode of mswait configured in node setup. ! 123: 2.21 ! 124: Added user's real name/company name (user_realname) to XTRN.DAT ! 125: 2.22 ! 126: Added usernumber() function to get user number from a user name. ! 127: 2.23 ! 128: DTE rate (com_rate) now a ulong (instead of uint) to allow 115.2K ! 129: 2.24 ! 130: New K_AUTODEL mode for getstr() function, to be used in conjunction ! 131: with the K_EDIT mode. Makes overwriting existing strings very ! 132: easy for users. ! 133: Supports intelligent timeslice APIs while waiting for a key with ! 134: getkey() and with getstr() if K_LOWPRIO mode is used. ! 135: Hitting Ctrl-C sets the 'aborted' variable to 1. ! 136: Time zone and daylight savings automatically initialized to 0. ! 137: Modem strings up to 63 chars in XTRN.DAT now supported. ! 138: Fixed 10 character zip code bug in XSDKVARS.C. ! 139: Node directories (node_dir) up to 127 chars now supported. ! 140: nopen() can now open DENYNONE if passed access O_DENYNONE. ! 141: 2.30 ! 142: Added support for the following Ctrl-A codes: ;,.<>[]A ! 143: Changed definitions of TAB, SP, etc. to hex ! 144: 2.31 ! 145: C restriction disallows users to use Ctrl-P. ! 146: T exemption disables "Time's up" message. ! 147: Added center() function for outputting centered lines of text. ! 148: Added auto-pause to cls() and outchar() functions when clearing ! 149: the screen and lncntr is greater than 1 ! 150: Changed bstrlen() to not count control characters (CR,LF,TAB,etc) ! 151: XSDK is now Watcom C++ compatible (although SBJ.C and SBL.C aren't) ! 152: XSDK.H is now *.CPP compatible ! 153: Added support for Ctrl-AQ (reset pause) and Ctrl-AZ (premature EOF) ! 154: 2.32 ! 155: Change bstrlen(char *str) to bstrlen(uchar *str) ! 156: Fixed bug in getstr() when word-wrapping a line that contains ! 157: ctrl-a codes and the input string did not begin at column 1. ! 158: Added user_dce variable (initialized by initdata from XTRN.DAT) ! 159: Fixed printnodedat() to not show Waiting for call (M) ! 160: Fixed typo in C restriction Ctrl-P message. ! 161: Moved call of checkline() in getkey() to immediately abort when ! 162: user hangs-up, even when keys are in the input buffer. ! 163: Added setmode() call to initdata() to set stderr to binary mode ! 164: Changed putchar() to write() in outchar() to elminate LF to CRLF ! 165: expansion ! 166: 2.33 ! 167: Improved cls() routine for auto-pause feature. ! 168: Added get_term() automatic RIP and WIP terminal detection function. ! 169: 2.34 ! 170: Added exec_dir, text_dir, and temp_dir variables to XTRN.DAT ! 171: format and initdata() function. ! 172: Added _fullpath() calls to initdata() to fix dir paths. ! 173: Added sys_id (QWK ID) to XTRN.DAT format and initdat() func. ! 174: Added node_misc to XTRN.DAT format and initdata() function. ! 175: If NM_LOWPRIO (low priority string input) is toggled on in ! 176: node_misc, then time-slices are always given up during input. ! 177: XSDK is now Symantec C++ compatible ! 178: 2.40 ! 179: node_misc was being read as a decimal number (it's stored in ! 180: the XTRN.DAT as hex), thus causing time-slice APIs to not ! 181: function correctly. ! 182: 2.41 ! 183: Ctrl-T is now intercepted by inkey() and displays the time the ! 184: program was launched, the current time, time used, and time ! 185: left (similar to SBBS). ! 186: Users are now warned of their last 5 minutes available (like SBBS). ! 187: 2.42 ! 188: ! 189: \****************************************************************************/ ! 190: ! 191: #include "xsdk.h" ! 192: ! 193: char *xsdk_ver="2.42"; ! 194: ! 195: #ifdef __TURBOC__ ! 196: extern long timezone=0L; ! 197: extern daylight=0; ! 198: #endif ! 199: ! 200: #ifdef __SC__ ! 201: #include <disp.h> ! 202: short wherey(void); ! 203: void clrscr(void); ! 204: #endif ! 205: ! 206: ! 207: /****************************************************************************/ ! 208: /* This allows users to abort the listing of text by using Ctrl-C */ ! 209: /****************************************************************************/ ! 210: int cbreakh(void) /* ctrl-break handler */ ! 211: { ! 212: aborted=1; ! 213: return(1); /* 1 to continue, 0 to abort */ ! 214: } ! 215: ! 216: /****************************************************************************/ ! 217: /* Performs printf() using bbs bputs function */ ! 218: /****************************************************************************/ ! 219: int bprintf(char *fmt, ...) ! 220: { ! 221: va_list argptr; ! 222: char sbuf[1024]; ! 223: int chcount; ! 224: ! 225: va_start(argptr,fmt); ! 226: chcount=vsprintf(sbuf,fmt,argptr); ! 227: va_end(argptr); ! 228: bputs(sbuf); ! 229: return(chcount); ! 230: } ! 231: ! 232: /****************************************************************************/ ! 233: /* Performs printf() using bbs rputs function */ ! 234: /****************************************************************************/ ! 235: int rprintf(char *fmt, ...) ! 236: { ! 237: va_list argptr; ! 238: char sbuf[1024]; ! 239: int chcount; ! 240: ! 241: va_start(argptr,fmt); ! 242: chcount=vsprintf(sbuf,fmt,argptr); ! 243: va_end(argptr); ! 244: rputs(sbuf); ! 245: return(chcount); ! 246: } ! 247: ! 248: /****************************************************************************/ ! 249: /* Outputs a NULL terminated string locally and remotely (if applicable) */ ! 250: /****************************************************************************/ ! 251: void bputs(char *str) ! 252: { ! 253: ulong l=0; ! 254: ! 255: while(str[l] && !aborted) { ! 256: if(str[l]==1) { /* ctrl-a */ ! 257: ctrl_a(str[++l]); /* skip the ctrl-a */ ! 258: if(str[l]=='Z') /* Ctrl-AZ marks premature end of file */ ! 259: break; ! 260: l++; } /* skip the attribute code */ ! 261: else ! 262: outchar(str[l++]); } ! 263: } ! 264: ! 265: /****************************************************************************/ ! 266: /* Outputs a NULL terminated string locally and remotely (if applicable) */ ! 267: /* Does not process ctrl-a codes (raw output) */ ! 268: /* Max length of str is 64 kbytes */ ! 269: /****************************************************************************/ ! 270: void rputs(char *str) ! 271: { ! 272: ulong l=0; ! 273: ! 274: while(str[l]) ! 275: outchar(str[l++]); ! 276: } ! 277: ! 278: /****************************************************************************/ ! 279: /* Returns the number of characters in 'str' not counting ctrl-ax codes */ ! 280: /* or the null terminator */ ! 281: /****************************************************************************/ ! 282: int bstrlen(uchar *str) ! 283: { ! 284: int i=0; ! 285: ! 286: while(*str) { ! 287: if(*str<SP) { /* ctrl char */ ! 288: if(*str==1) /* ctrl-A */ ! 289: str++; ! 290: else if(*str!=CR && *str!=LF && *str!=FF) ! 291: i++; } ! 292: else ! 293: i++; ! 294: if(!(*str)) ! 295: break; ! 296: str++; } ! 297: return(i); ! 298: } ! 299: ! 300: /****************************************************************************/ ! 301: /* Outputs the string 'str' centered for an 80 column display */ ! 302: /* Automatically appends "\r\n" to output */ ! 303: /****************************************************************************/ ! 304: void center(char *str) ! 305: { ! 306: int i,j; ! 307: ! 308: j=bstrlen(str); ! 309: for(i=0;i<(80-j)/2;i++) ! 310: outchar(SP); ! 311: bputs(str); ! 312: } ! 313: ! 314: /****************************************************************************/ ! 315: /* Outputs one character to the screen. Handles, pause, saving and */ ! 316: /* restoring lines, etc. */ ! 317: /****************************************************************************/ ! 318: void outchar(char ch) ! 319: { ! 320: ! 321: write(fileno(con_fp),&ch,1); ! 322: ! 323: if(ch==LF) { ! 324: lncntr++; ! 325: lbuflen=0; ! 326: tos=0; } ! 327: else if(ch==FF) { ! 328: if(lncntr>1) { ! 329: lncntr=0; ! 330: CRLF; ! 331: pause(); } ! 332: lncntr=0; ! 333: lbuflen=0; ! 334: tos=1; } ! 335: else if(ch==BS) { ! 336: if(lbuflen) ! 337: lbuflen--; } ! 338: else { ! 339: if(!lbuflen) ! 340: latr=curatr; ! 341: if(lbuflen>=LINE_BUFSIZE) lbuflen=0; ! 342: lbuf[lbuflen++]=ch; } ! 343: if(lncntr==user_rows-1) { ! 344: lncntr=0; ! 345: pause(); } ! 346: } ! 347: ! 348: /****************************************************************************/ ! 349: /* Prints PAUSE message and waits for a key stoke */ ! 350: /****************************************************************************/ ! 351: void pause(void) ! 352: { ! 353: uchar tempattrs=curatr,*msg="\1_\1r\1h[Hit a key] "; ! 354: int i,j; ! 355: ! 356: lncntr=0; ! 357: bputs(msg); ! 358: j=bstrlen(msg); ! 359: getkey(0); ! 360: for(i=0;i<j;i++) ! 361: bputs("\b \b"); ! 362: attr(tempattrs); ! 363: } ! 364: ! 365: /****************************************************************************/ ! 366: /* Prompts user for Y or N (yes or no) and CR is interpreted as a Y */ ! 367: /* Returns 1 for Y or 0 for N */ ! 368: /* Called from quite a few places */ ! 369: /****************************************************************************/ ! 370: char yesno(char *str) ! 371: { ! 372: char ch; ! 373: ! 374: bprintf("\1_\1b\1h%s (Y/n) ? \1w",str); ! 375: while(1) { ! 376: ch=getkey(K_UPPER); ! 377: if(ch=='Y' || ch==CR) { ! 378: bputs("Yes\r\n"); ! 379: return(1); } ! 380: if(ch=='N' || aborted) { ! 381: bputs("No\r\n"); ! 382: return(0); } } ! 383: } ! 384: ! 385: /****************************************************************************/ ! 386: /* Prompts user for N or Y (no or yes) and CR is interpreted as a N */ ! 387: /* Returns 1 for N or 0 for Y */ ! 388: /* Called from quite a few places */ ! 389: /****************************************************************************/ ! 390: char noyes(char *str) ! 391: { ! 392: char ch; ! 393: ! 394: bprintf("\1_\1b\1h%s (y/N) ? \1w",str); ! 395: while(1) { ! 396: ch=getkey(K_UPPER); ! 397: if(ch=='N' || ch==CR || aborted) { ! 398: bputs("No\r\n"); ! 399: return(1); } ! 400: if(ch=='Y') { ! 401: bputs("Yes\r\n"); ! 402: return(0); } } ! 403: } ! 404: ! 405: /****************************************************************************/ ! 406: /* Outputs a string highlighting characters preceeded by a tilde with the */ ! 407: /* color specified in mnehigh and the rest of the line is in color mnelow. */ ! 408: /* If the user doesn't have ANSI, it puts the character following the tilde */ ! 409: /* in parenthesis. */ ! 410: /****************************************************************************/ ! 411: void mnemonics(char *str) ! 412: { ! 413: long l; ! 414: ! 415: attr(mnelow); ! 416: l=0L; ! 417: while(str[l]) { ! 418: if(str[l]=='~' && str[l+1]) { ! 419: if(!(user_misc&ANSI)) ! 420: outchar('('); ! 421: l++; ! 422: attr(mnehigh); ! 423: outchar(str[l]); ! 424: l++; ! 425: if(!(user_misc&ANSI)) ! 426: outchar(')'); ! 427: attr(mnelow); } ! 428: else ! 429: outchar(str[l++]); } ! 430: attr(LIGHTGRAY); ! 431: } ! 432: ! 433: /****************************************************************************/ ! 434: /* If a key has been pressed, the ASCII code is returned. If not, 0 is */ ! 435: /* returned. Ctrl-P and Ctrl-U are intercepted here. */ ! 436: /****************************************************************************/ ! 437: char inkey(int mode) ! 438: { ! 439: static in_ctrl_p; ! 440: uchar ch=0,hour,min,sec; ! 441: ushort tleft; ! 442: uint i; ! 443: time_t now; ! 444: ! 445: if(keybufbot!=keybuftop) { ! 446: ch=keybuf[keybufbot++]; ! 447: if(keybufbot==KEY_BUFSIZE) ! 448: keybufbot=0; } ! 449: else if(_bios_keybrd(1)) { ! 450: i=_bios_keybrd(0); ! 451: if(i&0xff) ! 452: ch=i&0xff; ! 453: else { /* Local Alt or Function key hit */ ! 454: i>>=8; ! 455: switch(i) { ! 456: case 0x47: /* Home - Same as Ctrl-B */ ! 457: return(2); /* ctrl-b beginning of line */ ! 458: case 0x4b: /* Left Arrow - same as ctrl-] */ ! 459: return(0x1d); ! 460: case 0x4d: /* Right Arrow - same as ctrl-f */ ! 461: return(6); ! 462: case 0x48: /* Up arrow - same as ctrl-^ */ ! 463: return(0x1e); ! 464: case 0x50: /* Down arrow - same as CR */ ! 465: return(CR); ! 466: case 0x4f: /* End - same as Ctrl-E */ ! 467: return(5); /* ctrl-e - end of line */ ! 468: case 0x52: /* Insert */ ! 469: return(0x1f); /* ctrl-minus - insert mode */ ! 470: case 0x53: /* Delete */ ! 471: return(0x7f); /* ctrl-bkspc - del cur char */ ! 472: } ! 473: return(0); } } ! 474: ! 475: if(ch==0x10 || ch==0x1e) { /* Ctrl-P or Ctrl-^ */ ! 476: if(in_ctrl_p || !ctrl_dir[0]) /* keep from being recursive */ ! 477: return(0); ! 478: in_ctrl_p=1; ! 479: SAVELINE; ! 480: CRLF; ! 481: nodemsg(); ! 482: CRLF; ! 483: RESTORELINE; ! 484: lncntr=0; ! 485: in_ctrl_p=0; ! 486: return(0); } ! 487: ! 488: if(ch==20) { /* Ctrl-T Time left online */ ! 489: SAVELINE; ! 490: attr(LIGHTGRAY); ! 491: now=time(NULL); ! 492: checktimeleft(); ! 493: CRLF; ! 494: bprintf("\r\nStart : %.24s",ctime(&starttime)); ! 495: bprintf("\r\nNow : %.24s",ctime(&now)); ! 496: i=now-starttime; ! 497: hour=(i/60)/60; ! 498: min=(i/60)-(hour*60); ! 499: sec=i-((min+(hour*60))*60); ! 500: bprintf("\r\nTime Used : %02u:%02u:%02u",hour,min,sec); ! 501: tleft=timeleft-(now-starttime); ! 502: hour=(tleft/60)/60; ! 503: min=(tleft/60)-(hour*60); ! 504: sec=tleft-((min+(hour*60))*60); ! 505: bprintf("\r\nTime Left : %02u:%02u:%02u\r\n\r\n",hour,min,sec); ! 506: RESTORELINE; ! 507: lncntr=0; ! 508: return(0); } ! 509: ! 510: if(ch==21) { /* Ctrl-U Users online */ ! 511: if(!ctrl_dir[0]) ! 512: return(0); ! 513: SAVELINE; ! 514: CRLF; ! 515: whos_online(1); ! 516: CRLF; ! 517: RESTORELINE; ! 518: lncntr=0; ! 519: return(0); } ! 520: ! 521: if(ch==3) ! 522: aborted=1; ! 523: else if(aborted) ! 524: ch=3; ! 525: ! 526: if(!ch && (!(mode&K_GETSTR) || mode&K_LOWPRIO|| node_misc&NM_LOWPRIO)) ! 527: mswait(0); ! 528: return(ch); ! 529: } ! 530: ! 531: /****************************************************************************/ ! 532: /* Waits for remote or local user to hit a key. Inactivity timer is checked */ ! 533: /* and hangs up if inactive for 4 minutes. Returns key hit, or uppercase of */ ! 534: /* key hit if mode&K_UPPER or key out of KEY BUFFER. Does not print key. */ ! 535: /****************************************************************************/ ! 536: char getkey(int mode) ! 537: { ! 538: char ch,warn=0; ! 539: ushort tleft; ! 540: time_t timeout,now; ! 541: ! 542: aborted=lncntr=0; ! 543: timeout=time(NULL); ! 544: do { ! 545: checkline(); ! 546: ch=inkey(mode); ! 547: now=time(NULL); ! 548: if(ch) { ! 549: if(mode&K_NUMBER && isprint(ch) && !isdigit(ch)) ! 550: continue; ! 551: if(mode&K_ALPHA && isprint(ch) && !isalpha(ch)) ! 552: continue; ! 553: if(ch==LF) continue; ! 554: if(mode&K_UPPER) ! 555: return(toupper(ch)); ! 556: return(ch); } ! 557: checktimeleft(); ! 558: ! 559: tleft=timeleft-(now-starttime); ! 560: if((tleft/60)<(5-timeleft_warn)) { /* Running out of time warning */ ! 561: timeleft_warn=5-(tleft/60); ! 562: SAVELINE; ! 563: bprintf("&n&h\r\n\7\r\nYou only have &r&i%u&n&h minute%s " ! 564: "left.\r\n\r\n" ! 565: ,((ushort)tleft/60)+1,(tleft/60) ? "s" : ""); ! 566: RESTORELINE; } ! 567: ! 568: if(now-timeout>=sec_warn && !warn) /* Inactivity warning */ ! 569: for(warn=0;warn<5;warn++) ! 570: outchar(7); ! 571: } while(now-timeout<sec_timeout); ! 572: bputs("\r\nInactive too long.\r\n"); ! 573: exit(0); ! 574: return(0); /* never gets here, but makes compiler happy */ ! 575: } ! 576: ! 577: /****************************************************************************/ ! 578: /* If remote user, checks DCD to see if user has hung up or not. */ ! 579: /****************************************************************************/ ! 580: void checkline(void) ! 581: { ! 582: if(com_port && !((*msr)&DCD)) exit(0); ! 583: } ! 584: ! 585: /****************************************************************************/ ! 586: /* Waits for remote or local user to hit a key that is contained inside str.*/ ! 587: /* 'str' should contain uppercase characters only. When a valid key is hit, */ ! 588: /* it is echoed (upper case) and is the return value. */ ! 589: /* If max is non-zero and a number is hit that is not in str, it will be */ ! 590: /* returned with the high bit set. If the return of this function has the */ ! 591: /* high bit set (&0x8000), just flip the bit (^0x8000) to get the number. */ ! 592: /****************************************************************************/ ! 593: int getkeys(char *str,int max) ! 594: { ! 595: uchar ch,n=0; ! 596: int i=0; ! 597: ! 598: strupr(str); ! 599: while(!aborted) { ! 600: ch=getkey(K_UPPER); ! 601: if(max && ch>0x7f) /* extended ascii chars are digits to isdigit() */ ! 602: continue; ! 603: if(ch && !n && (strchr(str,ch))) { /* return character if in string */ ! 604: outchar(ch); ! 605: attr(LIGHTGRAY); ! 606: CRLF; ! 607: return(ch); } ! 608: if(ch==CR && max) { /* return 0 if no number */ ! 609: attr(LIGHTGRAY); ! 610: CRLF; ! 611: if(n) ! 612: return(i|0x8000); /* return number plus high bit */ ! 613: return(0); } ! 614: if(ch==BS && n) { ! 615: bputs("\b \b"); ! 616: i/=10; ! 617: n--; } ! 618: else if(max && isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) { ! 619: i*=10; ! 620: n++; ! 621: i+=ch&0xf; ! 622: outchar(ch); ! 623: if(i*10>max) { ! 624: attr(LIGHTGRAY); ! 625: CRLF; ! 626: return(i|0x8000); } } } ! 627: return(0); ! 628: } ! 629: ! 630: /****************************************************************************/ ! 631: /* Hot keyed number input routine. */ ! 632: /****************************************************************************/ ! 633: int getnum(int max) ! 634: { ! 635: uchar ch,n=0; ! 636: int i=0; ! 637: ! 638: while(1) { ! 639: ch=getkey(K_UPPER); ! 640: if(ch>0x7f) ! 641: continue; ! 642: if(ch=='Q') { ! 643: outchar('Q'); ! 644: CRLF; ! 645: return(-1); } ! 646: else if(ch==3) { /* ctrl-c */ ! 647: CRLF; ! 648: return(-1); } ! 649: else if(ch==CR) { ! 650: CRLF; ! 651: return(i); } ! 652: else if(ch==BS && n) { ! 653: bputs("\b \b"); ! 654: i/=10; ! 655: n--; } ! 656: else if(isdigit(ch) && (i*10)+(ch&0xf)<=max && (ch!='0' || n)) { ! 657: i*=10; ! 658: n++; ! 659: i+=ch&0xf; ! 660: outchar(ch); ! 661: if(i*10>max) { ! 662: CRLF; ! 663: return(i); } } } ! 664: return(-1); ! 665: } ! 666: ! 667: /****************************************************************************/ ! 668: /* Waits for remote or local user to input a CR terminated string. 'length' */ ! 669: /* is the maximum number of characters that getstr will allow the user to */ ! 670: /* input into the string. 'mode' specifies upper case characters are echoed */ ! 671: /* or wordwrap or if in message input (^A sequences allowed). ^W backspaces */ ! 672: /* a word, ^X backspaces a line, ^Gs, BSs, TABs are processed, LFs ignored. */ ! 673: /* ^N non-destructive BS, ^V center line. Valid keys are echoed. */ ! 674: /****************************************************************************/ ! 675: int getstr(char *strout, int maxlen, int mode) ! 676: { ! 677: int i,l,x,z; /* i=current position, l=length, j=printed chars */ ! 678: /* x&z=misc */ ! 679: uchar ch,str1[256],str2[256],ins=0,atr; ! 680: ! 681: if(mode&K_LINE && user_misc&ANSI) { ! 682: attr(LIGHTGRAY|HIGH|(BLUE<<4)); /* white on blue */ ! 683: for(i=0;i<maxlen;i++) ! 684: outchar(SP); ! 685: bprintf("\x1b[%dD",maxlen); } ! 686: i=l=0; /* i=total number of chars, j=number of printable chars */ ! 687: if(wordwrap[0]) { ! 688: strcpy(str1,wordwrap); ! 689: wordwrap[0]=0; } ! 690: else str1[0]=0; ! 691: if(mode&K_EDIT) ! 692: strcat(str1,strout); ! 693: if(strlen(str1)>maxlen) ! 694: str1[maxlen]=0; ! 695: atr=curatr; ! 696: if(mode&K_AUTODEL && str1[0]) ! 697: attr(BLUE|(LIGHTGRAY<<4)); ! 698: rputs(str1); ! 699: if(mode&K_EDIT && !(mode&(K_LINE|K_AUTODEL)) && user_misc&ANSI) ! 700: bputs("\x1b[K"); /* destroy to eol */ ! 701: i=l=strlen(str1); ! 702: ! 703: if(mode&K_AUTODEL && str1[0]) { ! 704: ch=getkey(mode); ! 705: attr(atr); ! 706: if(isprint(ch) || ch==0x7f) { ! 707: for(i=0;i<l;i++) ! 708: bputs("\b \b"); ! 709: i=l=0; } ! 710: else { ! 711: for(i=0;i<l;i++) ! 712: outchar(BS); ! 713: rputs(str1); ! 714: i=l; } ! 715: if(ch!=SP && ch!=TAB) ! 716: ungetkey(ch); } ! 717: ! 718: while((ch=getkey(mode|K_GETSTR))!=CR && !aborted) { ! 719: switch(ch) { ! 720: case 1: /* Ctrl-A for ANSI */ ! 721: if(!(mode&K_MSG) || i>maxlen-3) ! 722: break; ! 723: if(ins) { ! 724: if(l<maxlen) ! 725: l++; ! 726: for(x=l;x>i;x--) ! 727: str1[x]=str1[x-1]; ! 728: rprintf("%.*s",l-i,str1+i); ! 729: rprintf("\x1b[%dD",l-i); ! 730: if(i==maxlen-1) ! 731: ins=0; } ! 732: outchar(str1[i++]=1); ! 733: break; ! 734: case 2: /* Ctrl-B Beginning of Line */ ! 735: if(user_misc&ANSI && i) { ! 736: bprintf("\x1b[%dD",i); ! 737: i=0; } ! 738: break; ! 739: case 4: /* Ctrl-D Delete word right */ ! 740: if(i<l) { ! 741: x=i; ! 742: while(x<l && str1[x]!=SP) { ! 743: outchar(SP); ! 744: x++; } ! 745: while(x<l && str1[x]==SP) { ! 746: outchar(SP); ! 747: x++; } ! 748: bprintf("\x1b[%dD",x-i); /* move cursor back */ ! 749: z=i; ! 750: while(z<l-(x-i)) { /* move chars in string */ ! 751: outchar(str1[z]=str1[z+(x-i)]); ! 752: z++; } ! 753: while(z<l) { /* write over extra chars */ ! 754: outchar(SP); ! 755: z++; } ! 756: bprintf("\x1b[%dD",z-i); ! 757: l-=x-i; } /* l=new length */ ! 758: break; ! 759: case 5: /* Ctrl-E End of line */ ! 760: if(user_misc&ANSI && i<l) { ! 761: bprintf("\x1b[%dC",l-i); /* move cursor right one */ ! 762: i=l; } ! 763: break; ! 764: case 6: /* Ctrl-F move cursor forewards */ ! 765: if(i<l && (user_misc&ANSI)) { ! 766: bputs("\x1b[C"); /* move cursor right one */ ! 767: i++; } ! 768: break; ! 769: case 7: ! 770: if(!(mode&K_MSG)) ! 771: break; ! 772: if(ins) { ! 773: if(l<maxlen) ! 774: l++; ! 775: for(x=l;x>i;x--) ! 776: str1[x]=str1[x-1]; ! 777: if(i==maxlen-1) ! 778: ins=0; } ! 779: if(i<maxlen) { ! 780: str1[i++]=7; ! 781: outchar(7); } ! 782: break; ! 783: case 14: /* Ctrl-N Next word */ ! 784: if(i<l && (user_misc&ANSI)) { ! 785: x=i; ! 786: while(str1[i]!=SP && i<l) ! 787: i++; ! 788: while(str1[i]==SP && i<l) ! 789: i++; ! 790: bprintf("\x1b[%dC",i-x); } ! 791: break; ! 792: case 0x1c: /* Ctrl-\ Previous word */ ! 793: if(i && (user_misc&ANSI)) { ! 794: x=i; ! 795: while(str1[i-1]==SP && i) ! 796: i--; ! 797: while(str1[i-1]!=SP && i) ! 798: i--; ! 799: bprintf("\x1b[%dD",x-i); } ! 800: break; ! 801: case 18: /* Ctrl-R Redraw Line */ ! 802: redrwstr(str1,i,l,0); ! 803: break; ! 804: case TAB: ! 805: if(!(i%TABSIZE)) { ! 806: if(ins) { ! 807: if(l<maxlen) ! 808: l++; ! 809: for(x=l;x>i;x--) ! 810: str1[x]=str1[x-1]; ! 811: if(i==maxlen-1) ! 812: ins=0; } ! 813: str1[i++]=SP; ! 814: outchar(SP); } ! 815: while(i<maxlen && i%TABSIZE) { ! 816: if(ins) { ! 817: if(l<maxlen) ! 818: l++; ! 819: for(x=l;x>i;x--) ! 820: str1[x]=str1[x-1]; ! 821: if(i==maxlen-1) ! 822: ins=0; } ! 823: str1[i++]=SP; ! 824: outchar(SP); } ! 825: if(ins) ! 826: redrwstr(str1,i,l,0); ! 827: break; ! 828: case BS: ! 829: if(!i) ! 830: break; ! 831: i--; ! 832: l--; ! 833: if(i!=l) { /* Deleting char in middle of line */ ! 834: outchar(BS); ! 835: z=i; ! 836: while(z<l) { /* move the characters in the line */ ! 837: outchar(str1[z]=str1[z+1]); ! 838: z++; } ! 839: outchar(SP); /* write over the last char */ ! 840: bprintf("\x1b[%dD",(l-i)+1); } ! 841: else ! 842: bputs("\b \b"); ! 843: break; ! 844: case 22: /* Ctrl-V Center line */ ! 845: str1[l]=0; ! 846: l=bstrlen(str1); ! 847: for(x=0;x<(maxlen-l)/2;x++) ! 848: str2[x]=SP; ! 849: str2[x]=0; ! 850: strcat(str2,str1); ! 851: strcpy(strout,str2); ! 852: l=strlen(strout); ! 853: if(mode&K_MSG) ! 854: redrwstr(strout,i,l,K_MSG); ! 855: else { ! 856: while(i--) ! 857: bputs("\b"); ! 858: bputs(strout); ! 859: if(mode&K_LINE) ! 860: attr(LIGHTGRAY); } ! 861: CRLF; ! 862: return(l); ! 863: case 23: /* Ctrl-W Delete word left */ ! 864: if(i<l) { ! 865: x=i; /* x=original offset */ ! 866: while(i && str1[i-1]==SP) { ! 867: outchar(BS); ! 868: i--; } ! 869: while(i && str1[i-1]!=SP) { ! 870: outchar(BS); ! 871: i--; } ! 872: z=i; /* i=z=new offset */ ! 873: while(z<l-(x-i)) { /* move chars in string */ ! 874: outchar(str1[z]=str1[z+(x-i)]); ! 875: z++; } ! 876: while(z<l) { /* write over extra chars */ ! 877: outchar(SP); ! 878: z++; } ! 879: bprintf("\x1b[%dD",z-i); /* back to new x corridnant */ ! 880: l-=x-i; } /* l=new length */ ! 881: else { ! 882: while(i && str1[i-1]==SP) { ! 883: i--; ! 884: l--; ! 885: bputs("\b \b"); } ! 886: while(i && str1[i-1]!=SP) { ! 887: i--; ! 888: l--; ! 889: bputs("\b \b"); } } ! 890: break; ! 891: case 24: /* Ctrl-X Delete entire line */ ! 892: while(i<l) { ! 893: outchar(SP); ! 894: i++; } ! 895: while(l) { ! 896: l--; ! 897: bputs("\b \b"); } ! 898: i=0; ! 899: break; ! 900: case 25: /* Ctrl-Y Delete to end of line */ ! 901: if(user_misc&ANSI) { ! 902: bputs("\x1b[s\x1b[K\x1b[u"); ! 903: l=i; } ! 904: break; ! 905: case 31: /* Ctrl-Minus Toggles Insert/Overwrite */ ! 906: if(!(user_misc&ANSI)) ! 907: break; ! 908: if(ins) { ! 909: ins=0; ! 910: redrwstr(str1,i,l,0); } ! 911: else if(i<l) { ! 912: ins=1; ! 913: bprintf("\x1b[s\x1b[%dC",80-i); /* save pos */ ! 914: z=curatr; /* and got to EOL */ ! 915: attr(z|BLINK|HIGH); ! 916: outchar('�'); ! 917: attr(z); ! 918: bputs("\x1b[u"); } /* restore pos */ ! 919: break; ! 920: case 0x1d: /* Ctrl-] Reverse Cursor Movement */ ! 921: if(i && (user_misc&ANSI)) { ! 922: bputs("\x1b[D"); /* move cursor left one */ ! 923: i--; } ! 924: break; ! 925: case 0x7f: /* Ctrl-BkSpc (DEL) Delete current char */ ! 926: if(i==l) ! 927: break; ! 928: l--; ! 929: z=i; ! 930: while(z<l) { /* move the characters in the line */ ! 931: outchar(str1[z]=str1[z+1]); ! 932: z++; } ! 933: outchar(SP); /* write over the last char */ ! 934: bprintf("\x1b[%dD",(l-i)+1); ! 935: break; ! 936: case ESC: ! 937: if(!(user_misc&ANSI)) ! 938: break; ! 939: if((ch=getkey(0x8000))!='[') { ! 940: ungetch(ch); ! 941: break; } ! 942: if((ch=getkey(0x8000))=='C') { ! 943: if(i<l) { ! 944: bputs("\x1b[C"); /* move cursor right one */ ! 945: i++; } } ! 946: else if(ch=='D') { ! 947: if(i) { ! 948: bputs("\x1b[D"); /* move cursor left one */ ! 949: i--; } } ! 950: else { ! 951: while(isdigit(ch) || ch==';' || isalpha(ch)) { ! 952: if(isalpha(ch)) { ! 953: ch=getkey(0); ! 954: break; } ! 955: ch=getkey(0); } ! 956: ungetch(ch); } ! 957: break; ! 958: default: ! 959: if(mode&K_WRAP && i==maxlen && ch>=SP && !ins) { ! 960: str1[i]=0; ! 961: if(ch==SP) { /* don't wrap a space as last char */ ! 962: strcpy(strout,str1); ! 963: if(stripattr(strout)) ! 964: redrwstr(strout,i,l,K_MSG); ! 965: CRLF; ! 966: return(i); } ! 967: x=i-1; ! 968: z=1; ! 969: wordwrap[0]=ch; ! 970: while(str1[x]!=SP && x) ! 971: wordwrap[z++]=str1[x--]; ! 972: if(x<(maxlen/2)) { ! 973: wordwrap[1]=0; /* only wrap one character */ ! 974: strcpy(strout,str1); ! 975: if(stripattr(strout)) ! 976: redrwstr(strout,i,l,K_MSG); ! 977: CRLF; ! 978: return(i); } ! 979: wordwrap[z]=0; ! 980: while(z--) { ! 981: i--; ! 982: bputs("\b \b"); } ! 983: strrev(wordwrap); ! 984: str1[x]=0; ! 985: strcpy(strout,str1); ! 986: if(stripattr(strout)) ! 987: redrwstr(strout,i,x,mode); ! 988: CRLF; ! 989: return(x); } ! 990: if(i<maxlen && ch>=SP) { ! 991: if(mode&K_UPRLWR) ! 992: if(!i || (i && (str1[i-1]==SP || str1[i-1]=='-' ! 993: || str1[i-1]=='.' || str1[i-1]=='_'))) ! 994: ch=toupper(ch); ! 995: else ! 996: ch=tolower(ch); ! 997: if(ins) { ! 998: if(l<maxlen) /* l<maxlen */ ! 999: l++; ! 1000: for(x=l;x>i;x--) ! 1001: str1[x]=str1[x-1]; ! 1002: rprintf("%.*s",l-i,str1+i); ! 1003: rprintf("\x1b[%dD",l-i); ! 1004: if(i==maxlen-1) { ! 1005: bputs(" \b\b"); ! 1006: ins=0; } } ! 1007: str1[i++]=ch; ! 1008: outchar(ch); } } ! 1009: if(i>l) ! 1010: l=i; ! 1011: if(mode&K_CHAT && !l) ! 1012: return(0); } ! 1013: if(i>l) ! 1014: l=i; ! 1015: str1[l]=0; ! 1016: if(!aborted) { ! 1017: strcpy(strout,str1); ! 1018: if(stripattr(strout) || ins) ! 1019: redrwstr(strout,i,l,K_MSG); } ! 1020: else ! 1021: l=0; ! 1022: if(mode&K_LINE) attr(LIGHTGRAY); ! 1023: if(!(mode&K_NOCRLF)) { ! 1024: outchar(CR); ! 1025: if(!(mode&K_MSG && aborted)) ! 1026: outchar(LF); } ! 1027: return(l); ! 1028: } ! 1029: ! 1030: /****************************************************************************/ ! 1031: /* Redraws str using i as current cursor position and l as length */ ! 1032: /****************************************************************************/ ! 1033: void redrwstr(char *strin, int i, int l, char mode) ! 1034: { ! 1035: char str[256],c; ! 1036: ! 1037: sprintf(str,"%-*.*s",l,l,strin); ! 1038: c=i; ! 1039: while(c--) ! 1040: outchar(BS); ! 1041: if(mode&K_MSG) ! 1042: bputs(str); ! 1043: else ! 1044: rputs(str); ! 1045: if(user_misc&ANSI) { ! 1046: bputs("\x1b[K"); ! 1047: if(i<l) ! 1048: bprintf("\x1b[%dD",l-i); } ! 1049: else { ! 1050: while(c<79) { /* clear to end of line */ ! 1051: outchar(SP); ! 1052: c++; } ! 1053: while(c>l) { /* back space to end of string */ ! 1054: outchar(BS); ! 1055: c--; } } ! 1056: } ! 1057: ! 1058: /****************************************************************************/ ! 1059: /* Strips invalid Ctrl-Ax sequences from str */ ! 1060: /* Returns number of ^A's in line */ ! 1061: /****************************************************************************/ ! 1062: char stripattr(char *strin) ! 1063: { ! 1064: uchar str[81]; ! 1065: uchar a,c,d,e; ! 1066: ! 1067: e=strlen(strin); ! 1068: for(a=c=d=0;c<e;c++) { ! 1069: if(strin[c]==1) { ! 1070: a++; ! 1071: switch(toupper(strin[c+1])) { ! 1072: case '-': /* clear */ ! 1073: case '_': /* clear */ ! 1074: case 'B': /* blue fg */ ! 1075: case 'C': /* cyan fg */ ! 1076: case 'G': /* green fg */ ! 1077: case 'H': /* high fg */ ! 1078: case 'I': /* blink */ ! 1079: case 'K': /* black fg */ ! 1080: case 'L': /* cls */ ! 1081: case 'M': /* magenta fg */ ! 1082: case 'N': /* normal */ ! 1083: case 'P': /* pause */ ! 1084: case 'Q': /* pause reset */ ! 1085: case 'R': /* red fg */ ! 1086: case 'W': /* white fg */ ! 1087: case 'Y': /* yellow fg */ ! 1088: case '0': /* black bg */ ! 1089: case '1': /* red bg */ ! 1090: case '2': /* green bg */ ! 1091: case '3': /* brown bg */ ! 1092: case '4': /* blue bg */ ! 1093: case '5': /* magenta bg */ ! 1094: case '6': /* cyan bg */ ! 1095: case '7': /* white bg */ ! 1096: break; ! 1097: default: ! 1098: c++; ! 1099: continue; } } ! 1100: str[d++]=strin[c]; } ! 1101: str[d]=0; ! 1102: strcpy(strin,str); ! 1103: return(a); ! 1104: } ! 1105: ! 1106: /***************************************************************************/ ! 1107: /* Changes local and remote text attributes accounting for monochrome */ ! 1108: /***************************************************************************/ ! 1109: void attr(char atr) ! 1110: { ! 1111: ! 1112: if(!(user_misc&ANSI) || aborted) ! 1113: return; ! 1114: if(!(user_misc&COLOR)) { /* eliminate colors if user doesn't have them */ ! 1115: if(atr&LIGHTGRAY) /* if any bits set, set all */ ! 1116: atr|=LIGHTGRAY; ! 1117: if(atr&(LIGHTGRAY<<4)) ! 1118: atr|=(LIGHTGRAY<<4); ! 1119: if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4)) ! 1120: atr&=~LIGHTGRAY; } /* if background is solid, forground is black */ ! 1121: if(curatr==atr) /* attribute hasn't changed. don't send codes */ ! 1122: return; ! 1123: ! 1124: if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK) ! 1125: || atr==LIGHTGRAY) { ! 1126: bprintf("\x1b[0m"); ! 1127: curatr=LIGHTGRAY; } ! 1128: ! 1129: if(atr==LIGHTGRAY) { /* no attributes */ ! 1130: curatr=atr; ! 1131: return; } ! 1132: ! 1133: if(atr&BLINK) { /* special attributes */ ! 1134: if(!(curatr&BLINK)) ! 1135: bprintf("\x1b[5m"); } ! 1136: if(atr&HIGH) { ! 1137: if(!(curatr&HIGH)) ! 1138: bprintf("\x1b[1m"); } ! 1139: ! 1140: if((atr&0x7)==BLACK) { /* foreground colors */ ! 1141: if((curatr&0x7)!=BLACK) ! 1142: bprintf("\x1b[30m"); } ! 1143: else if((atr&0x7)==RED) { ! 1144: if((curatr&0x7)!=RED) ! 1145: bprintf("\x1b[31m"); } ! 1146: else if((atr&0x7)==GREEN) { ! 1147: if((curatr&0x7)!=GREEN) ! 1148: bprintf("\x1b[32m"); } ! 1149: else if((atr&0x7)==BROWN) { ! 1150: if((curatr&0x7)!=BROWN) ! 1151: bprintf("\x1b[33m"); } ! 1152: else if((atr&0x7)==BLUE) { ! 1153: if((curatr&0x7)!=BLUE) ! 1154: bprintf("\x1b[34m"); } ! 1155: else if((atr&0x7)==MAGENTA) { ! 1156: if((curatr&0x7)!=MAGENTA) ! 1157: bprintf("\x1b[35m"); } ! 1158: else if((atr&0x7)==CYAN) { ! 1159: if((curatr&0x7)!=CYAN) ! 1160: bprintf("\x1b[36m"); } ! 1161: else if((atr&0x7)==LIGHTGRAY) { ! 1162: if((curatr&0x7)!=LIGHTGRAY) ! 1163: bprintf("\x1b[37m"); } ! 1164: ! 1165: if((atr&0x70)==(BLACK<<4)) { /* background colors */ ! 1166: if((curatr&0x70)!=(BLACK<<4)) ! 1167: bprintf("\x1b[40m"); } ! 1168: else if((atr&0x70)==(RED<<4)) { ! 1169: if((curatr&0x70)!=(RED<<4)) ! 1170: bprintf("\x1b[41m"); } ! 1171: else if((atr&0x70)==(GREEN<<4)) { ! 1172: if((curatr&0x70)!=(GREEN<<4)) ! 1173: bprintf("\x1b[42m"); } ! 1174: else if((atr&0x70)==(BROWN<<4)) { ! 1175: if((curatr&0x70)!=(BROWN<<4)) ! 1176: bprintf("\x1b[43m"); } ! 1177: else if((atr&0x70)==(BLUE<<4)) { ! 1178: if((curatr&0x70)!=(BLUE<<4)) ! 1179: bprintf("\x1b[44m"); } ! 1180: else if((atr&0x70)==(MAGENTA<<4)) { ! 1181: if((curatr&0x70)!=(MAGENTA<<4)) ! 1182: bprintf("\x1b[45m"); } ! 1183: else if((atr&0x70)==(CYAN<<4)) { ! 1184: if((curatr&0x70)!=(CYAN<<4)) ! 1185: bprintf("\x1b[46m"); } ! 1186: else if((atr&0x70)==(LIGHTGRAY<<4)) { ! 1187: if((curatr&0x70)!=(LIGHTGRAY<<4)) ! 1188: bprintf("\x1b[47m"); } ! 1189: ! 1190: curatr=atr; ! 1191: } ! 1192: ! 1193: /****************************************************************************/ ! 1194: /* Peform clear screen */ ! 1195: /****************************************************************************/ ! 1196: void cls(void) ! 1197: { ! 1198: int i; ! 1199: ! 1200: if(lncntr>1 && !tos) { ! 1201: lncntr=0; ! 1202: CRLF; ! 1203: pause(); ! 1204: while(lncntr && !aborted) ! 1205: pause(); } ! 1206: ! 1207: if(user_misc&ANSI) ! 1208: bprintf("\x1b[2J"); ! 1209: else { ! 1210: outchar(FF); ! 1211: clrscr(); } ! 1212: tos=1; ! 1213: lncntr=0; ! 1214: } ! 1215: ! 1216: #ifdef __WATCOMC__ ! 1217: ! 1218: short wherey(void) ! 1219: { ! 1220: struct rccoord rc; ! 1221: ! 1222: rc=_gettextposition(); ! 1223: return(rc.col); ! 1224: } ! 1225: ! 1226: void clrscr(void) ! 1227: { ! 1228: _clearscreen(_GCLEARSCREEN); ! 1229: } ! 1230: ! 1231: #endif ! 1232: ! 1233: /****************************************************************************/ ! 1234: /* performs the correct attribute modifications for the Ctrl-A code */ ! 1235: /****************************************************************************/ ! 1236: void ctrl_a(char x) ! 1237: { ! 1238: char atr=curatr; ! 1239: int i,j; ! 1240: ! 1241: if((uchar)x>=0x7f) { ! 1242: if(user_misc&ANSI) ! 1243: bprintf("\x1b[%uC",(uchar)x-0x7f); ! 1244: else ! 1245: for(i=0;i<(uchar)x-0x7f;i++) ! 1246: outchar(SP); ! 1247: return; } ! 1248: ! 1249: switch(toupper(x)) { ! 1250: case '-': /* turn off all attributes if */ ! 1251: if(atr&(HIGH|BLINK|(LIGHTGRAY<<4))) /* high intensity, blink or */ ! 1252: attr(LIGHTGRAY); /* background bits are set */ ! 1253: break; ! 1254: case '_': /* turn off all attributes if */ ! 1255: if(atr&(BLINK|(LIGHTGRAY<<4))) /* blink or background is set */ ! 1256: attr(LIGHTGRAY); ! 1257: break; ! 1258: case ',': /* Delay 1/10 sec */ ! 1259: mswait(100); ! 1260: break; ! 1261: case ';': /* Delay 1/2 sec */ ! 1262: mswait(500); ! 1263: break; ! 1264: case '.': /* Delay 2 secs */ ! 1265: mswait(2000); ! 1266: break; ! 1267: case 'P': /* Pause */ ! 1268: pause(); ! 1269: break; ! 1270: case 'Q': /* Pause reset */ ! 1271: lncntr=0; ! 1272: break; ! 1273: case 'L': /* CLS (form feed) */ ! 1274: cls(); ! 1275: break; ! 1276: case '>': /* CLREOL */ ! 1277: if(user_misc&ANSI) ! 1278: bputs("\x1b[K"); ! 1279: else { ! 1280: i=j=wherey(); ! 1281: while(i++<80) ! 1282: outchar(SP); ! 1283: while(j++<80) ! 1284: outchar(BS); } ! 1285: break; ! 1286: case '<': /* Non-destructive backspace */ ! 1287: outchar(BS); ! 1288: break; ! 1289: case '[': /* Carriage return */ ! 1290: outchar(CR); ! 1291: break; ! 1292: case ']': /* Line feed */ ! 1293: outchar(LF); ! 1294: break; ! 1295: case 'A': /* Ctrl-A */ ! 1296: outchar(1); ! 1297: break; ! 1298: case 'H': /* High intensity */ ! 1299: atr|=HIGH; ! 1300: attr(atr); ! 1301: break; ! 1302: case 'I': /* Blink */ ! 1303: atr|=BLINK; ! 1304: attr(atr); ! 1305: break; ! 1306: case 'N': /* Normal */ ! 1307: attr(LIGHTGRAY); ! 1308: break; ! 1309: case 'R': ! 1310: atr=(atr&0xf8)|RED; ! 1311: attr(atr); ! 1312: break; ! 1313: case 'S': ! 1314: nodesync(); ! 1315: break; ! 1316: case 'G': ! 1317: atr=(atr&0xf8)|GREEN; ! 1318: attr(atr); ! 1319: break; ! 1320: case 'B': ! 1321: atr=(atr&0xf8)|BLUE; ! 1322: attr(atr); ! 1323: break; ! 1324: case 'W': /* White */ ! 1325: atr=(atr&0xf8)|LIGHTGRAY; ! 1326: attr(atr); ! 1327: break; ! 1328: case 'C': ! 1329: atr=(atr&0xf8)|CYAN; ! 1330: attr(atr); ! 1331: break; ! 1332: case 'M': ! 1333: atr=(atr&0xf8)|MAGENTA; ! 1334: attr(atr); ! 1335: break; ! 1336: case 'Y': ! 1337: atr=(atr&0xf8)|BROWN; ! 1338: attr(atr); ! 1339: break; ! 1340: case 'K': /* Black */ ! 1341: atr=(atr&0xf8)|BLACK; ! 1342: attr(atr); ! 1343: break; ! 1344: case '0': /* Black Background */ ! 1345: atr=(atr&0x8f)|(BLACK<<4); ! 1346: attr(atr); ! 1347: break; ! 1348: case '1': /* Red Background */ ! 1349: atr=(atr&0x8f)|(RED<<4); ! 1350: attr(atr); ! 1351: break; ! 1352: case '2': /* Green Background */ ! 1353: atr=(atr&0x8f)|(GREEN<<4); ! 1354: attr(atr); ! 1355: break; ! 1356: case '3': /* Yellow Background */ ! 1357: atr=(atr&0x8f)|(BROWN<<4); ! 1358: attr(atr); ! 1359: break; ! 1360: case '4': /* Blue Background */ ! 1361: atr=(atr&0x8f)|(BLUE<<4); ! 1362: attr(atr); ! 1363: break; ! 1364: case '5': /* Magenta Background */ ! 1365: atr=(atr&0x8f)|(MAGENTA<<4); ! 1366: attr(atr); ! 1367: break; ! 1368: case '6': /* Cyan Background */ ! 1369: atr=(atr&0x8f)|(CYAN<<4); ! 1370: attr(atr); ! 1371: break; ! 1372: case '7': /* White Background */ ! 1373: atr=(atr&0x8f)|(LIGHTGRAY<<4); ! 1374: attr(atr); ! 1375: break; } ! 1376: } ! 1377: ! 1378: /****************************************************************************/ ! 1379: /* Network open function. Opens all files DENYALL and retries LOOP_NOPEN */ ! 1380: /* number of times if the attempted file is already open or denying access */ ! 1381: /* for some other reason. All files are opened in BINARY mode. */ ! 1382: /****************************************************************************/ ! 1383: int nopen(char *str, int access) ! 1384: { ! 1385: char count=0; ! 1386: int file,share; ! 1387: ! 1388: if(access&SH_DENYNO) share=SH_DENYNO; ! 1389: else if(access==O_RDONLY) share=SH_DENYWR; ! 1390: else share=SH_DENYRW; ! 1391: while(((file=sopen(str,O_BINARY|access,share,S_IWRITE))==-1) ! 1392: && errno==EACCES && count++<LOOP_NOPEN) ! 1393: if(count>10) ! 1394: mswait(50); ! 1395: if(count>(LOOP_NOPEN/2) && count<=LOOP_NOPEN) ! 1396: bprintf("\r\nNOPEN COLLISION - File: %s Count: %d\r\n" ! 1397: ,str,count); ! 1398: if(file==-1 && errno==EACCES) ! 1399: bputs("\7\r\nNOPEN: ACCESS DENIED\r\n\7"); ! 1400: return(file); ! 1401: } ! 1402: ! 1403: /****************************************************************************/ ! 1404: /* Reads data from XTRN.DAT in the node directory and fills the appropriate */ ! 1405: /* global variables. */ ! 1406: /* Initializes starttime variable with current time. */ ! 1407: /****************************************************************************/ ! 1408: void initdata(void) ! 1409: { ! 1410: char str[256],tmp[256]; ! 1411: int i; ! 1412: FILE *stream; ! 1413: ! 1414: #if defined(__TURBOC__) || defined(__SC__) /* Borland or Symantec */ ! 1415: ctrlbrk(cbreakh); ! 1416: #endif ! 1417: ! 1418: #ifdef __WATCOMC__ ! 1419: putenv("TZ=UCT0"); ! 1420: setvbuf(stdout,NULL,_IONBF,0); ! 1421: setvbuf(stderr,NULL,_IONBF,0); ! 1422: #endif ! 1423: ! 1424: #ifdef __SC__ ! 1425: setvbuf(stdout,NULL,_IONBF,0); ! 1426: con_fp=stdout; ! 1427: #else ! 1428: con_fp=stderr; ! 1429: #endif ! 1430: ! 1431: if(setmode(fileno(con_fp),O_BINARY)==-1) { /* eliminate LF expansion */ ! 1432: printf("Can't set console output to BINARY\n"); ! 1433: exit(1); } ! 1434: ! 1435: sprintf(str,"%sXTRN.DAT",node_dir); ! 1436: if((stream=fopen(str,"rt"))==NULL) { ! 1437: printf("Can't open %s\r\n",str); ! 1438: exit(1); } ! 1439: fgets(str,81,stream); /* username */ ! 1440: sprintf(user_name,"%.25s",str); ! 1441: truncsp(user_name); ! 1442: fgets(str,81,stream); /* system name */ ! 1443: sprintf(sys_name,"%.40s",str); ! 1444: truncsp(sys_name); ! 1445: fgets(str,81,stream); /* system operator */ ! 1446: sprintf(sys_op,"%.40s",str); ! 1447: truncsp(sys_op); ! 1448: fgets(str,81,stream); /* system guru */ ! 1449: sprintf(sys_guru,"%.40s",str); ! 1450: truncsp(sys_guru); ! 1451: ! 1452: fgets(str,81,stream); /* ctrl dir */ ! 1453: str[50]=0; ! 1454: if(str[0]=='.') ! 1455: sprintf(ctrl_dir,"%s%s",node_dir,str); ! 1456: else ! 1457: strcpy(ctrl_dir,str); ! 1458: truncsp(ctrl_dir); ! 1459: if(_fullpath(str,ctrl_dir,50)) ! 1460: strcpy(ctrl_dir,str); ! 1461: backslash(ctrl_dir); ! 1462: ! 1463: fgets(str,81,stream); /* data dir */ ! 1464: if(str[0]=='.') ! 1465: sprintf(data_dir,"%s%s",node_dir,str); ! 1466: else ! 1467: sprintf(data_dir,"%.40s",str); ! 1468: truncsp(data_dir); ! 1469: if(_fullpath(str,data_dir,50)) ! 1470: strcpy(data_dir,str); ! 1471: backslash(data_dir); ! 1472: ! 1473: fgets(str,81,stream); /* total nodes */ ! 1474: sys_nodes=atoi(str); ! 1475: fgets(str,81,stream); /* current node */ ! 1476: node_num=atoi(str); ! 1477: fgets(str,81,stream); /* time left */ ! 1478: timeleft=atoi(str); ! 1479: fgets(str,81,stream); /* ANSI? (Yes, Mono, or No) */ ! 1480: user_misc=0; ! 1481: if(str[0]=='Y') ! 1482: user_misc|=(ANSI|COLOR); ! 1483: else if(str[0]=='M') ! 1484: user_misc|=ANSI; ! 1485: fgets(str,81,stream); /* screen lines */ ! 1486: user_rows=atoi(str); ! 1487: fgets(str,81,stream); /* credits */ ! 1488: user_cdt=atol(str); ! 1489: fgets(str,81,stream); /* level */ ! 1490: user_level=atoi(str); ! 1491: fgets(str,81,stream); /* was transfer level, left for compat. */ ! 1492: fgets(str,81,stream); /* birthdate */ ! 1493: truncsp(str); ! 1494: sprintf(user_birth,"%.8s",str); ! 1495: fgets(str,81,stream); /* sex */ ! 1496: user_sex=str[0]; ! 1497: fgets(str,81,stream); /* user number */ ! 1498: user_number=atoi(str); ! 1499: fgets(str,81,stream); /* user phone number */ ! 1500: sprintf(user_phone,"%.12s",str); ! 1501: truncsp(user_phone); ! 1502: fgets(str,81,stream); /* com port (0 if local or no modem) */ ! 1503: com_port=atoi(str); ! 1504: fgets(str,81,stream); /* com (UART) irq */ ! 1505: com_irq=atoi(str); ! 1506: fgets(str,81,stream); /* com (UART) base address in hex */ ! 1507: truncsp(str); ! 1508: com_base=(uint)ahtoul(str); ! 1509: fgets(str,81,stream); /* com rate */ ! 1510: com_rate=(ulong)atol(str); ! 1511: fgets(str,81,stream); /* hardware flow control (Y/N) */ ! 1512: if(toupper(str[0])=='Y') ! 1513: mdm_misc|=MDM_FLOWCTRL; ! 1514: fgets(str,81,stream); /* locked DTE rate (Y/N) */ ! 1515: if(toupper(str[0])=='Y') ! 1516: mdm_misc|=MDM_STAYHIGH; ! 1517: fgets(str,81,stream); /* modem initialization string */ ! 1518: sprintf(mdm_init,"%.63s",str); ! 1519: truncsp(mdm_init); ! 1520: fgets(str,81,stream); /* modem special init string */ ! 1521: sprintf(mdm_spec,"%.63s",str); ! 1522: truncsp(mdm_spec); ! 1523: fgets(str,81,stream); /* modem terminal mode string */ ! 1524: sprintf(mdm_term,"%.63s",str); ! 1525: truncsp(mdm_term); ! 1526: fgets(str,81,stream); /* modem dial string */ ! 1527: sprintf(mdm_dial,"%.63s",str); ! 1528: truncsp(mdm_dial); ! 1529: fgets(str,81,stream); /* modem off-hook string */ ! 1530: sprintf(mdm_offh,"%.63s",str); ! 1531: truncsp(mdm_offh); ! 1532: fgets(str,81,stream); /* modem answer string */ ! 1533: sprintf(mdm_answ,"%.63s",str); ! 1534: truncsp(mdm_answ); ! 1535: fgets(str,81,stream); /* memory address of modem status register */ ! 1536: msr=(uint far *)atol(str); ! 1537: if(!fgets(str,81,stream)) /* total number of external programs */ ! 1538: total_xtrns=0; ! 1539: else ! 1540: total_xtrns=atoi(str); ! 1541: if(total_xtrns && (xtrn=(char **)MALLOC(sizeof(char *)*total_xtrns))==NULL) { ! 1542: printf("Allocation error 1: %u\r\n",sizeof(char *)*total_xtrns); ! 1543: exit(1); } ! 1544: for(i=0;i<total_xtrns;i++) { ! 1545: fgets(str,81,stream); ! 1546: truncsp(str); ! 1547: if((xtrn[i]=(char *)MALLOC(strlen(str)+1))==NULL) { ! 1548: printf("Allocation error 2 (%u): %u\r\n",i,strlen(str)+1); ! 1549: exit(1); } ! 1550: strcpy(xtrn[i],str); } ! 1551: fgets(str,81,stream); /* user's main flags */ ! 1552: sprintf(user_flags1,"%.26s",str); ! 1553: fgets(str,81,stream); /* user's xfer flags */ ! 1554: sprintf(user_flags2,"%.26s",str); ! 1555: fgets(str,81,stream); /* user's exemptions */ ! 1556: sprintf(user_exempt,"%.26s",str); ! 1557: fgets(str,81,stream); /* user's restrictions */ ! 1558: sprintf(user_rest,"%.26s",str); ! 1559: fgets(str,81,stream); /* user's expiration date */ ! 1560: truncsp(str); ! 1561: user_expire=ahtoul(str); ! 1562: str[0]=0; ! 1563: fgets(str,81,stream); /* user's address */ ! 1564: sprintf(user_address,"%.30s",str); ! 1565: truncsp(user_address); ! 1566: fgets(str,81,stream); /* user's location (city, state) */ ! 1567: sprintf(user_location,"%.30s",str); ! 1568: truncsp(user_location); ! 1569: fgets(str,81,stream); /* user's zip/postal code */ ! 1570: sprintf(user_zipcode,"%.10s",str); ! 1571: truncsp(user_zipcode); ! 1572: str[0]=0; ! 1573: fgets(str,81,stream); ! 1574: sprintf(user_flags3,"%.26s",str); ! 1575: fgets(str,81,stream); ! 1576: sprintf(user_flags4,"%.26s",str); ! 1577: if(fgets(str,81,stream)) /* Time-slice API type */ ! 1578: mswtyp=ahtoul(str); ! 1579: str[0]=0; ! 1580: fgets(str,81,stream); ! 1581: truncsp(str); ! 1582: sprintf(user_realname,"%.25s",str); ! 1583: str[0]=0; ! 1584: fgets(str,81,stream); ! 1585: user_dce=atol(str); ! 1586: ! 1587: str[0]=0; ! 1588: fgets(str,81,stream); /* exec dir */ ! 1589: if(!str[0]) ! 1590: sprintf(exec_dir,"%s..\\EXEC\\",ctrl_dir); ! 1591: else { ! 1592: if(str[0]=='.') ! 1593: sprintf(exec_dir,"%s%s",node_dir,str); ! 1594: else ! 1595: sprintf(exec_dir,"%.50s",str); } ! 1596: truncsp(exec_dir); ! 1597: if(_fullpath(str,exec_dir,50)) ! 1598: strcpy(exec_dir,str); ! 1599: backslash(exec_dir); ! 1600: ! 1601: str[0]=0; ! 1602: fgets(str,81,stream); /* text dir */ ! 1603: if(!str[0]) ! 1604: sprintf(text_dir,"%s..\\TEXT\\",ctrl_dir); ! 1605: else { ! 1606: if(str[0]=='.') ! 1607: sprintf(text_dir,"%s%s",node_dir,str); ! 1608: else ! 1609: sprintf(text_dir,"%.50s",str); } ! 1610: truncsp(text_dir); ! 1611: if(_fullpath(str,text_dir,50)) ! 1612: strcpy(text_dir,str); ! 1613: backslash(text_dir); ! 1614: ! 1615: str[0]=0; ! 1616: fgets(str,81,stream); /* temp dir */ ! 1617: if(!str[0]) ! 1618: sprintf(temp_dir,"%sTEMP\\",node_dir); ! 1619: else { ! 1620: if(str[0]!='\\' && str[1]!=':') ! 1621: sprintf(temp_dir,"%s%s",node_dir,str); ! 1622: else ! 1623: sprintf(temp_dir,"%.50s",str); } ! 1624: truncsp(temp_dir); ! 1625: if(_fullpath(str,temp_dir,50)) ! 1626: strcpy(temp_dir,str); ! 1627: backslash(temp_dir); ! 1628: ! 1629: str[0]=0; ! 1630: fgets(str,81,stream); ! 1631: sprintf(sys_id,"%.8s",str); ! 1632: ! 1633: str[0]=0; ! 1634: fgets(str,81,stream); ! 1635: truncsp(str); ! 1636: if(str[0]) ! 1637: node_misc=(uint)ahtoul(str); ! 1638: else ! 1639: node_misc=NM_LOWPRIO; ! 1640: ! 1641: fclose(stream); ! 1642: ! 1643: sprintf(str,"%sINTRSBBS.DAT",node_dir); /* Shrank to run! */ ! 1644: if(fexist(str)) { ! 1645: if((stream=fopen(str,"rt"))==NULL) { ! 1646: printf("Can't open %s\n",str); ! 1647: exit(1); } ! 1648: fgets(tmp,81,stream); /* so get MSR address from file */ ! 1649: msr=(uint far *)atol(tmp); ! 1650: fclose(stream); ! 1651: remove(str); } ! 1652: ! 1653: starttime=time(NULL); /* initialize start time stamp */ ! 1654: wordwrap[0]=0; /* set wordwrap to null */ ! 1655: attr(LIGHTGRAY); /* initialize color and curatr to plain */ ! 1656: mnehigh=LIGHTGRAY|HIGH; /* mnemonics highlight color */ ! 1657: mnelow=GREEN; /* mnemonics normal text color */ ! 1658: sec_warn=180; /* seconds till inactivity warning */ ! 1659: sec_timeout=300; /* seconds till inactivity timeout */ ! 1660: tos=lncntr=0; /* init topofscreen and linecounter to 0 */ ! 1661: lastnodemsg=0; /* Last node to send message to */ ! 1662: aborted=0; /* Ctrl-C hit flag */ ! 1663: sysop_level=90; /* Minimum level to be considered sysop */ ! 1664: timeleft_warn=0; /* Running out of time warning */ ! 1665: ! 1666: sprintf(str,"%s%s",ctrl_dir,"NODE.DAB"); ! 1667: if((nodefile=sopen(str,O_BINARY|O_RDWR,SH_DENYNO))==-1) { ! 1668: bprintf("\r\n\7Error opening %s\r\n",str); ! 1669: exit(1); } ! 1670: ! 1671: sprintf(str,"%sUSER\\NAME.DAT",data_dir); ! 1672: if((i=nopen(str,O_RDONLY))==-1) { ! 1673: printf("\r\n\7Error opening %s\r\n",str); ! 1674: exit(1); } ! 1675: memset(str,0,30); ! 1676: read(i,str,26); ! 1677: close(i); ! 1678: if(str[25]==CR) /* Version 1b */ ! 1679: name_len=25; ! 1680: else /* Version 1a */ ! 1681: name_len=30; ! 1682: } ! 1683: ! 1684: /****************************************************************************/ ! 1685: /* Automatic RIP & WIP terminal detection function. Sets RIP and WIP bits */ ! 1686: /* in user_misc variable. Must be called AFTER initdat(), not before. */ ! 1687: /****************************************************************************/ ! 1688: void get_term(void) ! 1689: { ! 1690: char str[128],ch; ! 1691: int i; ! 1692: ! 1693: bputs("\r\x1b[!_\x1b[0t_\r \r"); ! 1694: mswait(500); ! 1695: for(i=0;i<120;i++) { ! 1696: ch=inkey(0); ! 1697: if(!ch) ! 1698: break; ! 1699: mswait(1); ! 1700: str[i]=ch; } ! 1701: str[i]=0; ! 1702: if(strstr(str,"RIPSCRIP")) ! 1703: user_misc|=RIP; ! 1704: if(strstr(str,"DC-TERM")) ! 1705: user_misc|=WIP; ! 1706: } ! 1707: ! 1708: /****************************************************************************/ ! 1709: /* Truncates white-space chars off end of 'str' and terminates at first tab */ ! 1710: /****************************************************************************/ ! 1711: void truncsp(uchar *str) ! 1712: { ! 1713: char c; ! 1714: ! 1715: str[strcspn(str,"\t")]=0; ! 1716: c=strlen(str); ! 1717: while(c && (uchar)str[c-1]<=SP) c--; ! 1718: str[c]=0; ! 1719: } ! 1720: ! 1721: /****************************************************************************/ ! 1722: /* Puts a backslash on path strings */ ! 1723: /****************************************************************************/ ! 1724: void backslash(char *str) ! 1725: { ! 1726: int i; ! 1727: ! 1728: i=strlen(str); ! 1729: if(i && str[i-1]!='\\') { ! 1730: str[i]='\\'; str[i+1]=0; } ! 1731: } ! 1732: ! 1733: ! 1734: /****************************************************************************/ ! 1735: /* Checks the amount of time inside the external program against the amount */ ! 1736: /* of time the user had left online before running the external program and */ ! 1737: /* prints a message and exits the program if time has run out. */ ! 1738: /****************************************************************************/ ! 1739: void checktimeleft(void) ! 1740: { ! 1741: if(!SYSOP && !strchr(user_exempt,'T') && time(NULL)-starttime>timeleft) { ! 1742: bputs("\1_\n\1r\1hTime's up.\n"); ! 1743: exit(0); } ! 1744: } ! 1745: ! 1746: /****************************************************************************/ ! 1747: /* Prints a file remotely and locally, interpreting ^A sequences. */ ! 1748: /* 'str' is the path of the file to print */ ! 1749: /****************************************************************************/ ! 1750: void printfile(char *str) ! 1751: { ! 1752: char *buf; ! 1753: int file; ! 1754: ulong length; ! 1755: ! 1756: strupr(str); ! 1757: if(!tos) ! 1758: CRLF; ! 1759: if((file=nopen(str,O_RDONLY))==-1) { ! 1760: bprintf("File not Found: %s\r\n",str); ! 1761: return; } ! 1762: length=filelength(file); ! 1763: if((buf=MALLOC(length+1L))==NULL) { ! 1764: close(file); ! 1765: bprintf("\7\r\nPRINTFILE: Error allocating %lu bytes of memory for %s.\r\n" ! 1766: ,length+1L,str); ! 1767: return; } ! 1768: buf[read(file,buf,length)]=0; ! 1769: close(file); ! 1770: bputs(buf); ! 1771: aborted=0; ! 1772: FREE(buf); ! 1773: } ! 1774: ! 1775: /****************************************************************************/ ! 1776: /* Returns a char pointer to the name of the user that corresponds to */ ! 1777: /* usernumber. Takes value directly from database. */ ! 1778: /****************************************************************************/ ! 1779: char *username(uint usernumber) ! 1780: { ! 1781: static char name[26]; ! 1782: char str[128]; ! 1783: int i,file; ! 1784: ! 1785: strcpy(name,"UNKNOWN USER"); ! 1786: if(!data_dir[0]) ! 1787: return(name); ! 1788: if(!usernumber) { ! 1789: bputs("\7username: called with zero usernumber\r\n"); ! 1790: return(name); } ! 1791: sprintf(str,"%sUSER\\NAME.DAT",data_dir); ! 1792: if((file=nopen(str,O_RDONLY))==-1) { ! 1793: bprintf("\7username: couldn't open %s\r\n",str); ! 1794: return(name); } ! 1795: if(filelength(file)<(long)(usernumber-1)*((long)name_len+2L)) { ! 1796: close(file); ! 1797: return(name); } ! 1798: lseek(file,(long)(usernumber-1)*((long)name_len+2L),SEEK_SET); ! 1799: read(file,name,25); ! 1800: close(file); ! 1801: for(i=0;i<25;i++) ! 1802: if(name[i]==3) ! 1803: break; ! 1804: name[i]=0; ! 1805: if(!name[0]) ! 1806: strcpy(name,"DELETED USER"); ! 1807: return(name); ! 1808: } ! 1809: ! 1810: /****************************************************************************/ ! 1811: /* Returns the number of the user 'username' from the NAME.DAT file. */ ! 1812: /* If the username is not found, the function returns 0. */ ! 1813: /****************************************************************************/ ! 1814: uint usernumber(char *username) ! 1815: { ! 1816: char str[128]; ! 1817: int i,file; ! 1818: FILE *stream; ! 1819: ! 1820: if(!data_dir[0]) ! 1821: return(0); ! 1822: sprintf(str,"%sUSER\\NAME.DAT",data_dir); ! 1823: if((file=nopen(str,O_RDONLY))==-1 || (stream=fdopen(file,"rb"))==NULL) { ! 1824: if(file!=-1) ! 1825: close(file); ! 1826: bprintf("\7usernumber: couldn't open %s\r\n",str); ! 1827: return(0); } ! 1828: for(i=1;!feof(stream);i++) { ! 1829: if(!fread(str,27,1,stream)) ! 1830: break; ! 1831: str[25]=0; ! 1832: truncsp(str); /* chop of trailing EOTs and spaces */ ! 1833: if(!stricmp(str,username)) { ! 1834: fclose(stream); ! 1835: return(i); } } ! 1836: fclose(stream); ! 1837: return(0); ! 1838: } ! 1839: ! 1840: ! 1841: /****************************************************************************/ ! 1842: /* Checks the disk drive for the existance of a file. Returns 1 if it */ ! 1843: /* exists, 0 if it doesn't. */ ! 1844: /* Called from upload */ ! 1845: /****************************************************************************/ ! 1846: char fexist(char *filespec) ! 1847: { ! 1848: #ifdef __SC__ /* Symantec */ ! 1849: if(findfirst(filespec,0)==NULL) ! 1850: return(0); ! 1851: return(1); ! 1852: #else /* Not Symantec */ ! 1853: struct ffblk f; ! 1854: ! 1855: if(findfirst(filespec,&f,0)==NULL) ! 1856: return(1); ! 1857: return(0); ! 1858: #endif /* !__SC__ */ ! 1859: } ! 1860: ! 1861: /****************************************************************************/ ! 1862: /* Returns the length of the first file found that matches 'filespec' */ ! 1863: /* -1 if the file doesn't exist. */ ! 1864: /****************************************************************************/ ! 1865: long flength(char *filespec) ! 1866: { ! 1867: #ifdef __SC__ /* Symantec */ ! 1868: struct FILE *f; ! 1869: ! 1870: if((f=findfirst(filespec,0))==NULL) ! 1871: return(-1); ! 1872: return(f->size); ! 1873: ! 1874: #else /* Not Symantec */ ! 1875: ! 1876: struct ffblk f; ! 1877: ! 1878: if(findfirst(filespec,&f,0)==NULL) ! 1879: #ifdef __TURBOC__ /* Borland */ ! 1880: return(f.ff_fsize); ! 1881: #else /* Other (Watcom) */ ! 1882: return(f.size); ! 1883: #endif ! 1884: return(-1L); ! 1885: #endif /* !__SC__ */ ! 1886: } ! 1887: ! 1888: /****************************************************************************/ ! 1889: /* Returns in 'string' a character representation of the number in l with */ ! 1890: /* commas. Maximum value of l is 4 gigabytes. */ ! 1891: /****************************************************************************/ ! 1892: char *ultoac(ulong l, char *string) ! 1893: { ! 1894: char str[81]; ! 1895: char i,j,k; ! 1896: ! 1897: ultoa(l,str,10); ! 1898: i=strlen(str)-1; ! 1899: j=i/3+1+i; ! 1900: string[j--]=0; ! 1901: for(k=1;i>-1;k++) { ! 1902: string[j--]=str[i--]; ! 1903: if(j>0 && !(k%3)) ! 1904: string[j--]=','; } ! 1905: return(string); ! 1906: } ! 1907: ! 1908: /****************************************************************************/ ! 1909: /* Converts an ASCII Hex string into a ulong */ ! 1910: /****************************************************************************/ ! 1911: ulong ahtoul(char *str) ! 1912: { ! 1913: ulong l,val=0; ! 1914: ! 1915: while((l=(*str++)|0x20)!=0x20) ! 1916: val=(l&0xf)+(l>>6&1)*9+val*16; ! 1917: return(val); ! 1918: } ! 1919: ! 1920: /****************************************************************************/ ! 1921: /* Reads the data for node number 'number' into the structure 'node' */ ! 1922: /* from NODE.DAB */ ! 1923: /* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */ ! 1924: /****************************************************************************/ ! 1925: void getnodedat(uchar number, node_t *node, char lockit) ! 1926: { ! 1927: char str[256]; ! 1928: int count=0; ! 1929: ! 1930: if(nodefile<0) ! 1931: return; ! 1932: number--; /* make zero based */ ! 1933: while(count<LOOP_NODEDAB) { ! 1934: lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET); ! 1935: if(lockit ! 1936: && lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))==-1) { ! 1937: count++; ! 1938: continue; } ! 1939: if(read(nodefile,node,sizeof(node_t))==sizeof(node_t)) ! 1940: break; ! 1941: count++; } ! 1942: if(count==LOOP_NODEDAB) ! 1943: bprintf("\7Error unlocking and reading NODE.DAB\r\n"); ! 1944: } ! 1945: ! 1946: /****************************************************************************/ ! 1947: /* Write the data from the structure 'node' into NODE.DAB */ ! 1948: /* getnodedat(num,&node,1); must have been called before calling this func */ ! 1949: /* NOTE: ------^ the indicates the node record has been locked */ ! 1950: /****************************************************************************/ ! 1951: void putnodedat(uchar number, node_t node) ! 1952: { ! 1953: char str[256]; ! 1954: int count; ! 1955: ! 1956: if(nodefile<0) ! 1957: return; ! 1958: number--; /* make zero based */ ! 1959: lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET); ! 1960: if(write(nodefile,&node,sizeof(node_t))!=sizeof(node_t)) { ! 1961: unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t)); ! 1962: bprintf("\7Error writing NODE.DAB for node %u\r\n",number+1); ! 1963: return; } ! 1964: unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t)); ! 1965: } ! 1966: ! 1967: /****************************************************************************/ ! 1968: /* Checks for messages waiting for this node or interruption. */ ! 1969: /****************************************************************************/ ! 1970: void nodesync(void) ! 1971: { ! 1972: node_t node; ! 1973: ! 1974: if(!ctrl_dir[0]) ! 1975: return; ! 1976: getnodedat(node_num,&node,0); ! 1977: ! 1978: if(node.misc&NODE_MSGW) ! 1979: getsmsg(user_number); /* getsmsg clears MSGW flag */ ! 1980: ! 1981: if(node.misc&NODE_NMSG) /* getnmsg clears NMSG flag */ ! 1982: getnmsg(); ! 1983: ! 1984: if(node.misc&NODE_INTR) ! 1985: exit(0); ! 1986: ! 1987: } ! 1988: ! 1989: /****************************************************************************/ ! 1990: /* Displays the information for node number 'number' contained in 'node' */ ! 1991: /****************************************************************************/ ! 1992: void printnodedat(uchar number, node_t node) ! 1993: { ! 1994: char hour,mer[3],tmp[256]; ! 1995: int i; ! 1996: ! 1997: attr(LIGHTGRAY|HIGH); ! 1998: bprintf("Node %2d: ",number); ! 1999: attr(GREEN); ! 2000: switch(node.status) { ! 2001: case NODE_WFC: ! 2002: bputs("Waiting for call"); ! 2003: break; ! 2004: case NODE_OFFLINE: ! 2005: bputs("Offline"); ! 2006: break; ! 2007: case NODE_NETTING: ! 2008: bputs("Networking"); ! 2009: break; ! 2010: case NODE_LOGON: ! 2011: bputs("At logon prompt"); ! 2012: break; ! 2013: case NODE_EVENT_WAITING: ! 2014: bputs("Waiting for all nodes to become inactive"); ! 2015: break; ! 2016: case NODE_EVENT_LIMBO: ! 2017: bprintf("Waiting for node %d to finish external event",node.aux); ! 2018: break; ! 2019: case NODE_EVENT_RUNNING: ! 2020: bputs("Running external event"); ! 2021: break; ! 2022: case NODE_NEWUSER: ! 2023: attr(GREEN|HIGH); ! 2024: bputs("New user"); ! 2025: attr(GREEN); ! 2026: bputs(" applying for access "); ! 2027: if(!node.connection) ! 2028: bputs("Locally"); ! 2029: else ! 2030: bprintf("at %ubps",node.connection); ! 2031: break; ! 2032: case NODE_QUIET: ! 2033: if(!SYSOP) { ! 2034: bputs("Waiting for call"); ! 2035: break; } ! 2036: case NODE_INUSE: ! 2037: attr(GREEN|HIGH); ! 2038: if(node.misc&NODE_ANON && !SYSOP) ! 2039: bputs("UNKNOWN USER"); ! 2040: else ! 2041: bputs(username(node.useron)); ! 2042: attr(GREEN); ! 2043: bputs(" "); ! 2044: switch(node.action) { ! 2045: case NODE_MAIN: ! 2046: bputs("at main menu"); ! 2047: break; ! 2048: case NODE_RMSG: ! 2049: bputs("reading messages"); ! 2050: break; ! 2051: case NODE_RMAL: ! 2052: bputs("reading mail"); ! 2053: break; ! 2054: case NODE_RSML: ! 2055: bputs("reading sent mail"); ! 2056: break; ! 2057: case NODE_RTXT: ! 2058: bputs("reading text files"); ! 2059: break; ! 2060: case NODE_PMSG: ! 2061: bputs("posting message"); ! 2062: break; ! 2063: case NODE_SMAL: ! 2064: bputs("sending mail"); ! 2065: break; ! 2066: case NODE_AMSG: ! 2067: bputs("posting auto-message"); ! 2068: break; ! 2069: case NODE_XTRN: ! 2070: if(!node.aux) ! 2071: bputs("at external program menu"); ! 2072: else { ! 2073: bputs("running "); ! 2074: i=node.aux-1; ! 2075: if(i>=total_xtrns || !xtrn[i][0]) ! 2076: bputs("external program"); ! 2077: else ! 2078: bputs(xtrn[i]); } ! 2079: break; ! 2080: case NODE_DFLT: ! 2081: bputs("changing defaults"); ! 2082: break; ! 2083: case NODE_XFER: ! 2084: bputs("at transfer menu"); ! 2085: break; ! 2086: case NODE_RFSD: ! 2087: bprintf("retrieving from device #%d",node.aux); ! 2088: break; ! 2089: case NODE_DLNG: ! 2090: bprintf("downloading"); ! 2091: break; ! 2092: case NODE_ULNG: ! 2093: bputs("uploading"); ! 2094: break; ! 2095: case NODE_BXFR: ! 2096: bputs("transferring bidirectional"); ! 2097: break; ! 2098: case NODE_LFIL: ! 2099: bputs("listing files"); ! 2100: break; ! 2101: case NODE_LOGN: ! 2102: bputs("logging on"); ! 2103: break; ! 2104: case NODE_LCHT: ! 2105: bprintf("in local chat with %s",sys_op); ! 2106: break; ! 2107: case NODE_MCHT: ! 2108: if(node.aux) { ! 2109: bprintf("in multinode chat channel %d",node.aux&0xff); ! 2110: if(node.aux&0x1f00) /* password */ ! 2111: outchar('*'); } ! 2112: else ! 2113: bputs("in multinode global chat channel"); ! 2114: break; ! 2115: case NODE_PAGE: ! 2116: bprintf("paging node %u for private chat",node.aux); ! 2117: break; ! 2118: case NODE_PCHT: ! 2119: bprintf("in private chat with node %u",node.aux); ! 2120: break; ! 2121: case NODE_GCHT: ! 2122: bprintf("chatting with %s",sys_guru); ! 2123: break; ! 2124: case NODE_CHAT: ! 2125: bputs("in chat section"); ! 2126: break; ! 2127: case NODE_TQWK: ! 2128: bputs("transferring QWK packet"); ! 2129: break; ! 2130: case NODE_SYSP: ! 2131: bputs("performing sysop activities"); ! 2132: break; ! 2133: default: ! 2134: bputs(itoa(node.action,tmp,10)); ! 2135: break; } ! 2136: if(!node.connection) ! 2137: bputs(" locally"); ! 2138: else ! 2139: bprintf(" at %ubps",node.connection); ! 2140: if(node.action==NODE_DLNG) { ! 2141: if((node.aux/60)>12) { ! 2142: hour=(node.aux/60)-12; ! 2143: strcpy(mer,"pm"); } ! 2144: else { ! 2145: if((node.aux/60)==0) /* 12 midnite */ ! 2146: hour=12; ! 2147: else hour=node.aux/60; ! 2148: strcpy(mer,"am"); } ! 2149: bprintf(" ETA %02d:%02d %s" ! 2150: ,hour,node.aux%60,mer); } ! 2151: break; } ! 2152: i=NODE_LOCK; ! 2153: if(node.status==NODE_INUSE || SYSOP) ! 2154: i|=NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG; ! 2155: if(node.misc&i) { ! 2156: bputs(" ("); ! 2157: if(node.misc&(i&NODE_AOFF)) ! 2158: outchar('A'); ! 2159: if(node.misc&NODE_LOCK) ! 2160: outchar('L'); ! 2161: if(node.misc&(i&(NODE_MSGW|NODE_NMSG))) ! 2162: outchar('M'); ! 2163: if(node.misc&(i&NODE_POFF)) ! 2164: outchar('P'); ! 2165: outchar(')'); } ! 2166: if(SYSOP && ((node.misc ! 2167: &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN)) ! 2168: || node.status==NODE_QUIET)) { ! 2169: bputs(" ["); ! 2170: if(node.misc&NODE_ANON) ! 2171: outchar('A'); ! 2172: if(node.misc&NODE_INTR) ! 2173: outchar('I'); ! 2174: if(node.misc&NODE_RRUN) ! 2175: outchar('R'); ! 2176: if(node.misc&NODE_UDAT) ! 2177: outchar('U'); ! 2178: if(node.status==NODE_QUIET) ! 2179: outchar('Q'); ! 2180: if(node.misc&NODE_EVENT) ! 2181: outchar('E'); ! 2182: if(node.misc&NODE_DOWN) ! 2183: outchar('D'); ! 2184: outchar(']'); } ! 2185: if(node.errors && SYSOP) { ! 2186: attr(RED|HIGH|BLINK); ! 2187: bprintf(" %d error%c",node.errors, node.errors>1 ? 's' : '\0' ); } ! 2188: CRLF; ! 2189: } ! 2190: ! 2191: /****************************************************************************/ ! 2192: /* Prints short messages waiting for 'usernumber', if any... */ ! 2193: /* then deletes them. */ ! 2194: /****************************************************************************/ ! 2195: void getsmsg(int usernumber) ! 2196: { ! 2197: char str[256], *buf; ! 2198: int file; ! 2199: long length; ! 2200: node_t node; ! 2201: ! 2202: if(!data_dir[0]) ! 2203: return; ! 2204: sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber); ! 2205: if(flength(str)<1L) { ! 2206: return; } ! 2207: if((file=nopen(str,O_RDWR))==-1) { ! 2208: bprintf("\7Error opening %s for read/write access\r\n",str); ! 2209: return; } ! 2210: length=filelength(file); ! 2211: if((buf=MALLOC(length+1))==NULL) { ! 2212: close(file); ! 2213: bprintf("\7Error allocating %u bytes of memory for %s\r\n",length+1,str); ! 2214: return; } ! 2215: if(read(file,buf,length)!=length) { ! 2216: close(file); ! 2217: FREE(buf); ! 2218: bprintf("\7Error reading %u bytes from %s\r\n",length,str); ! 2219: return; } ! 2220: chsize(file,0L); ! 2221: close(file); ! 2222: buf[length]=0; ! 2223: getnodedat(node_num,&node,0); ! 2224: if(node.action==NODE_MAIN || node.action==NODE_XFER) { ! 2225: CRLF; } ! 2226: if(node.misc&NODE_MSGW) { ! 2227: getnodedat(node_num,&node,1); ! 2228: node.misc&=~NODE_MSGW; ! 2229: putnodedat(node_num,node); } ! 2230: bputs(buf); ! 2231: FREE(buf); ! 2232: } ! 2233: ! 2234: /****************************************************************************/ ! 2235: /* Creates a short message for 'usernumber' than contains 'strin' */ ! 2236: /****************************************************************************/ ! 2237: void putsmsg(int usernumber, char *strin) ! 2238: { ! 2239: char str[256]; ! 2240: int file,i; ! 2241: node_t node; ! 2242: ! 2243: if(!data_dir[0]) ! 2244: return; ! 2245: sprintf(str,"%sMSGS\\%4.4u.MSG",data_dir,usernumber); ! 2246: if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) { ! 2247: bprintf("\7Error opening/creating %s for creat/append access\r\n",str); ! 2248: return; } ! 2249: i=strlen(strin); ! 2250: if(write(file,strin,i)!=i) { ! 2251: close(file); ! 2252: bprintf("\7Error writing %u bytes to %s\r\n",i,str); ! 2253: return; } ! 2254: close(file); ! 2255: for(i=1;i<=sys_nodes;i++) { /* flag node if user on that msg waiting */ ! 2256: getnodedat(i,&node,0); ! 2257: if(node.useron==usernumber ! 2258: && (node.status==NODE_INUSE || node.status==NODE_QUIET) ! 2259: && !(node.misc&NODE_MSGW)) { ! 2260: getnodedat(i,&node,1); ! 2261: node.misc|=NODE_MSGW; ! 2262: putnodedat(i,node); } } ! 2263: } ! 2264: ! 2265: /****************************************************************************/ ! 2266: /* Prints short messages waiting for this node, if any... */ ! 2267: /****************************************************************************/ ! 2268: void getnmsg(void) ! 2269: { ! 2270: char str[256], *buf; ! 2271: int file; ! 2272: long length; ! 2273: node_t thisnode; ! 2274: ! 2275: if(!data_dir[0]) ! 2276: return; ! 2277: getnodedat(node_num,&thisnode,1); ! 2278: thisnode.misc&=~NODE_NMSG; /* clear the NMSG flag */ ! 2279: putnodedat(node_num,thisnode); ! 2280: ! 2281: sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,node_num); ! 2282: if(flength(str)<1L) { ! 2283: return; } ! 2284: if((file=nopen(str,O_RDWR))==-1) { ! 2285: printf("Couldn't open %s for read/write\r\n",str); ! 2286: return; } ! 2287: length=filelength(file); ! 2288: if((buf=MALLOC(length+1))==NULL) { ! 2289: close(file); ! 2290: printf("Couldn't allocate %lu bytes for %s\r\n",length+1,str); ! 2291: return; } ! 2292: if(read(file,buf,length)!=length) { ! 2293: close(file); ! 2294: FREE(buf); ! 2295: printf("Couldn't read %lu bytes from %s\r\n",length,str); ! 2296: return; } ! 2297: chsize(file,0L); ! 2298: close(file); ! 2299: buf[length]=0; ! 2300: ! 2301: bputs(buf); ! 2302: FREE(buf); ! 2303: } ! 2304: ! 2305: /****************************************************************************/ ! 2306: /* Creates a short message for node 'num' than contains 'strin' */ ! 2307: /****************************************************************************/ ! 2308: void putnmsg(int num, char *strin) ! 2309: { ! 2310: char str[256]; ! 2311: int file,i; ! 2312: node_t node; ! 2313: ! 2314: if(!data_dir[0]) ! 2315: return; ! 2316: sprintf(str,"%sMSGS\\N%3.3u.MSG",data_dir,num); ! 2317: if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) { ! 2318: printf("Couldn't open %s for append\r\n",str); ! 2319: return; } ! 2320: i=strlen(strin); ! 2321: if(write(file,strin,i)!=i) { ! 2322: close(file); ! 2323: printf("Error writing %u bytes to %s\r\n",i,str); ! 2324: return; } ! 2325: close(file); ! 2326: getnodedat(num,&node,0); ! 2327: if((node.status==NODE_INUSE || node.status==NODE_QUIET) ! 2328: && !(node.misc&NODE_NMSG)) { ! 2329: getnodedat(num,&node,1); ! 2330: node.misc|=NODE_NMSG; ! 2331: putnodedat(num,node); } ! 2332: } ! 2333: ! 2334: /****************************************************************************/ ! 2335: /* This function lists users that are online. */ ! 2336: /* If listself is true, it will list the current node. */ ! 2337: /* Returns number of active nodes (not including current node). */ ! 2338: /****************************************************************************/ ! 2339: int whos_online(char listself) ! 2340: { ! 2341: int i,j; ! 2342: node_t node; ! 2343: ! 2344: if(!ctrl_dir[0]) ! 2345: return(0); ! 2346: CRLF; ! 2347: for(j=0,i=1;i<=sys_nodes;i++) { ! 2348: getnodedat(i,&node,0); ! 2349: if(i==node_num) { ! 2350: if(listself) ! 2351: printnodedat(i,node); ! 2352: continue; } ! 2353: if(node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) { ! 2354: printnodedat(i,node); ! 2355: if(!lastnodemsg) ! 2356: lastnodemsg=i; ! 2357: j++; } } ! 2358: if(!j) ! 2359: bputs("\1nNo other active nodes.\r\n"); ! 2360: return(j); ! 2361: } ! 2362: ! 2363: /****************************************************************************/ ! 2364: /* Sending single line messages between nodes */ ! 2365: /****************************************************************************/ ! 2366: void nodemsg(void) ! 2367: { ! 2368: char str[256],line[256],buf[512]; ! 2369: int i,j; ! 2370: node_t thisnode; ! 2371: node_t node; ! 2372: ! 2373: if(!ctrl_dir[0]) ! 2374: return; ! 2375: if(strchr(user_rest,'C')) { ! 2376: bputs("You cannot send messages.\r\n"); ! 2377: return; } ! 2378: getnodedat(node_num,&thisnode,0); ! 2379: wordwrap[0]=0; ! 2380: if(lastnodemsg) { ! 2381: getnodedat(lastnodemsg,&node,0); ! 2382: if(node.status!=NODE_INUSE) ! 2383: lastnodemsg=0; } ! 2384: if(!whos_online(0)) ! 2385: return; ! 2386: bprintf("\r\n&n&gNumber of node to send message to, &w&hA&n&gll, " ! 2387: "or &w&hQ&n&guit [%u]: &w&h",lastnodemsg); ! 2388: i=getkeys("QA",sys_nodes); ! 2389: if(i==-1) ! 2390: return; ! 2391: if(i&0x8000 || !i) { ! 2392: if(!i) ! 2393: i=lastnodemsg; ! 2394: else { ! 2395: i^=0x8000; ! 2396: lastnodemsg=i; } ! 2397: if(!i || i>sys_nodes) ! 2398: return; ! 2399: getnodedat(i,&node,0); ! 2400: if(node.status!=NODE_INUSE && !SYSOP) ! 2401: bprintf("\r\n&_&w&hNode %d is not in use.\r\n",i); ! 2402: else if(i==node_num) ! 2403: bputs("\r\nThere's no need to send a message to yourself.\r\n"); ! 2404: else if(node.misc&NODE_POFF && !SYSOP) ! 2405: bprintf("\r\n&r&h&iDon't bug %s.&n\r\n" ! 2406: ,node.misc&NODE_ANON ? "UNKNOWN USER" ! 2407: : username(node.useron)); ! 2408: else { ! 2409: bputs("&_&y&hMessage: "); ! 2410: if(!getstr(line,70,K_LINE)) ! 2411: return; ! 2412: sprintf(buf ! 2413: ,"\7&_&w&hNode %2d: &g%s&n&g sent you a message:\r\n&w&h&4%s&n\r\n" ! 2414: ,node_num ! 2415: ,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line); ! 2416: putnmsg(i,buf); } } ! 2417: else if(i=='A') { ! 2418: bputs("&_&y&hMessage: "); ! 2419: if(!getstr(line,70,K_LINE)) ! 2420: return; ! 2421: sprintf(buf ! 2422: ,"\7&_&w&hNode %2d: &g%s&n&g sent all nodes a message:\r\n" ! 2423: "&w&h&4%s&n\r\n" ! 2424: ,node_num ! 2425: ,thisnode.misc&NODE_ANON ? "UNKNOWN USER" : user_name,line); ! 2426: for(i=1;i<=sys_nodes;i++) { ! 2427: if(i==node_num) ! 2428: continue; ! 2429: getnodedat(i,&node,0); ! 2430: if((node.status==NODE_INUSE || (SYSOP && node.status==NODE_QUIET)) ! 2431: && (SYSOP || !(node.misc&NODE_POFF))) ! 2432: putnmsg(i,buf); } } ! 2433: ! 2434: } ! 2435: ! 2436: /****************************************************************************/ ! 2437: /* Puts a character into the input buffer */ ! 2438: /****************************************************************************/ ! 2439: void ungetkey(char ch) ! 2440: { ! 2441: ! 2442: keybuf[keybuftop++]=ch; ! 2443: if(keybuftop==KEY_BUFSIZE) ! 2444: keybuftop=0; ! 2445: } ! 2446: ! 2447: #ifdef __SC__ /* Missing from Symantec RTL */ ! 2448: void clrscr(void) ! 2449: { ! 2450: asm ! 2451: { mov ah,8 /*function # for "Get char with attr*/ ! 2452: xor bh,bh /*page 0*/ ! 2453: int 10h /*Call interrupt 10h (video)*/ ! 2454: ! 2455: mov bh,ah /*set "set attr" to "current attr"*/ ! 2456: mov ah,6 /*function # for "Scroll Window Up"*/ ! 2457: xor cx,cx /*set upper row & column (0,0)*/ ! 2458: xor al,al /*set "# lines to scroll" to 0*/ ! 2459: mov dh,119 /*set lowqer colum*/ ! 2460: int 10h /*Call interrupt 10h*/ ! 2461: ! 2462: mov ah,2 /*function # for "Set Cursor Position"*/ ! 2463: xor bh,bh /*set page to 0*/ ! 2464: xor dx,dx /*set row & colum to 0 (upper left)*/ ! 2465: int 10h /*Call interrupt 10h*/ ! 2466: } ! 2467: return; ! 2468: } ! 2469: ! 2470: short wherey(void) ! 2471: { ! 2472: struct disp_t rc; ! 2473: return(rc.cursorcol); ! 2474: } ! 2475: #endif /* __SC__ */ ! 2476:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.