Annotation of sbbs/sbbs2/sdk/xsdk.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.