home *** CD-ROM | disk | FTP | other *** search
- /*
- * System Dependent Server Message Handling
- * Net Bios
- *
- * This program is the CONFIDENTIAL and PROPRIETARY property
- * of FairCom(R) Corporation. Any unauthorized use, reproduction or
- * transfer of this program is strictly prohibited.
- *
- * Copyright (c) 1987, 1988, 1989 FairCom Corporation
- * (Subject to limited distribution and
- * restricted disclosure only.)
- * *** ALL RIGHTS RESERVED ***
- *
- * 4006 West Broadway
- * Columbia, MO 65203
- *
- *
- * c-tree(R) Version 4.3
- * Release C
- * February 7, 1989 17:30
- *
- */
-
- #include "ctstdr.h"
- #include "ctoptn.h"
- #include "ctstrc.h"
- #include "cterrc.h"
- #include "ctcomm.h"
-
- #include "ctnbio.h"
- #include "ctnbcfg.h"
-
- #ifdef FOREGROUND
- #include <dos.h>
- #endif
-
- LOCAL UCOUNT idle = 0;
- LOCAL UCOUNT kbcnt = 0;
- #define STRETCH 100
- #define KBFREQ 100
-
- typedef struct {
- short ax,bx,cx,dx,si,di,cflag;
- } XREGS;
-
- typedef struct {
- short es,cs,ss,ds;
- } SREGS;
-
-
- #define NOT_A_SESN 0xff /* illegal value for session number */
-
- #ifdef DEBUG
- #ifdef LOCAL
- #undef LOCAL
- #define LOCAL /* */
- #endif
- #endif
-
- typedef struct xncb
- {
- UCOUNT f; /* completed flag, set to 1 by anr */
- NCB n;
- } XNCB;
-
- LOCAL XNCB ncb; /* misc netbios control block */
- LOCAL XNCB lstncb; /* listen netbios control block */
- UTEXT srvname[] = SRV_NETNAME; /* server network name */
- LOCAL COUNT namenum = 0; /* name's number */
- LOCAL UTEXT *usr_to_ses; /* xlate ctree user number to netbios ses */
- LOCAL TEXT *usr_to_name; /* xlate to netbios name */
- LOCAL TEXT lastname[16]; /* name rcvd on TST_MSGSIZ message */
- LOCAL UTEXT act_ses[256]; /* 1 if session number of active session */
- LOCAL UCOUNT msgsiz; /* max message size */
- LOCAL UCOUNT usrmax; /* max number of users */
- LOCAL XNCB **rncb; /* ptrs to recv ncbs */
- LOCAL XNCB **sncb; /* ptrs to send ncbs */
- LOCAL UTEXT **rbuf; /* ptrs to recv bufs */
- LOCAL UTEXT **sbuf; /* ptrs to send ncbs */
- LOCAL UTEXT *contextbuf; /* used by asm to save dos state */
-
- LOCAL UCOUNT (far *fnulf)() = 0L; /* null int routine */
-
- extern UCOUNT far fanrf(); /* int routine called when ncb cmd complete */
-
- #ifndef FOREGROUND
- extern UCOUNT far task_wait(UCOUNT);
- extern UCOUNT far task_init(UTEXT far *);
- extern UCOUNT far task_preinit();
- extern UCOUNT far clear_task_events();
- #else
- extern VOID far fg_init();
- #endif
-
-
- extern COUNT uerr_cod;
- extern TEXT ct_buf[];
-
-
- TEXT *mballc();
-
-
- #ifdef FOREGROUND
- dlaymos()
- {
- XREGS dr;
-
- dr.ax = 0x0702;
- dr.bx = 0x0001;
-
- int86(0x38,&dr,&dr);
- }
-
- #endif
-
- /*
- * hook up to the network.
- */
-
- TEXT *getmid(sizmsg, maxusr)
- UCOUNT sizmsg;
- COUNT maxusr;
- {
- TEXT *retval;
- UCOUNT e, i, t;
- UTEXT *memcush; /* holds alloc'd mem to be freed */
- /* before term/stay resident */
- UCOUNT ctxsize;
-
- uerr_cod = 0; /* in case no error */
-
- usrmax = maxusr; /* save (used when cvrting sesn to usrn) */
-
- /* check for netbios installed */
-
- if (nb_install_check()) {
- uerr_cod = SSKY_ERR;
- return (NULL);
- }
-
- msgsiz = sizmsg; /* local max msg size for start_recv's */
-
- #ifndef FOREGROUND
- /* get size of task switch buffers (rets 0 if !dos3) */
- if (0 == (ctxsize = task_preinit())) {
- uerr_cod = SSKY_ERR; /* not dos 3.x */
- return (NULL);
- }
- #endif
-
- /* get current dir */
- if (get_default_dir())
- return (NULL);
-
- /*
- * allocate
- * retval - return to ctsrvr for message buffer
- * usr_to_ses - logical user to netbios session xlate table
- * usr_to_name - logical user to netbios name table
- * rbuf (sbuf) - ptr to array of ptrs to recv (send) bufs
- * rncb (sncb) - ptr to array of ptrs to recv (send) ncbs
- * contextbuf - used by asm lang (ctstsr) for task switch
- * memcush - reserve some space for alloc's after asm lang
- * cuts off ability to get mem from OS (will be
- * freed before returning)
- */
- if ( (usr_to_ses = (UTEXT *) mballc(maxusr + 1, sizeof(UTEXT))) == NULL
- || (usr_to_name = (TEXT *) mballc(maxusr, 16)) == NULL
- || (retval = (UTEXT *) mballc(1, sizmsg + sizeof(UCOUNT))) == NULL
- || (rbuf = (UTEXT **) mballc(SRV_RNCBS, sizeof(*rbuf))) == NULL
- || (rncb = (XNCB **) mballc(SRV_RNCBS, sizeof(*rncb))) == NULL
- || (sbuf = (UTEXT **) mballc(SRV_SNCBS, sizeof(*sbuf))) == NULL
- || (sncb = (XNCB **) mballc(SRV_SNCBS, sizeof(*sncb))) == NULL
- || (rbuf[0] = (UTEXT *) mballc(SRV_RNCBS, sizmsg)) == NULL
- || (rncb[0] = (XNCB *) mballc(SRV_RNCBS, sizeof(XNCB))) == NULL
- || (sbuf[0] = (UTEXT *) mballc(SRV_SNCBS, sizmsg)) == NULL
- || (sncb[0] = (XNCB *) mballc(SRV_SNCBS, sizeof(XNCB))) == NULL
- || (contextbuf = (UTEXT *) mballc(1, ctxsize)) == NULL
- || (memcush = (UTEXT *) mballc(1, MEM_CUSHION)) == NULL ) {
- uerr_cod = SSPC_ERR;
- return (NULL);
- }
-
- /*
- * init the usernum/sesnum xlate table
- */
-
- memset(usr_to_ses, NOT_A_SESN, maxusr+1);
-
- /* first word of ctsrvr's buffer is hidden and used here to
- * remember which session for last recv
- */
-
- retval += sizeof(UCOUNT);
-
- /* add name to network */
-
- if (e = nb_addname(&ncb.n, 0, fnulf, srvname)) {
- uerr_cod = SSID_ERR;
- return (NULL);
- }
-
- namenum = ncb.n.namenum; /* used to start recvs */
-
- /* init listen ncb */
-
- start_listen();
-
- /* init recv ncbs */
-
- for (i=0; i< SRV_RNCBS; i++) {
- /* finish building array of ptrs */
- rncb[i] = rncb[0] + i;
- rbuf[i] = rbuf[0] + i*sizmsg;
- start_recv(i); /* enable recvs */
- }
-
- /* init send ncbs */
- for (i=0; i< SRV_SNCBS; i++) {
- /* finish building array of ptrs */
- sncb[i] = sncb[0] + i;
- sbuf[i] = sbuf[0] + i*sizmsg;
- sncb[i]->f = 2; /* 2 means free send buffer */
- }
-
- /* fix up to allow eventual term/stay resident */
- #ifndef FOREGROUND
- task_init((UTEXT far *) contextbuf);
- #else
- fg_init();
- #endif
-
- free(memcush); /* return mem for alloc users */
-
- #ifdef FOREGROUND
- display_menu();
- #endif
-
- return (retval);
- }
-
- /*
- * undo the comm link
- */
-
- COUNT ridmid()
- {
- VOID far disconnect();
-
- disconnect();
- return (0);
- }
-
-
- /*
- * getumsg associates logical user number with session number
- * of last recv'd message. ctsrvr use's 0 to max-1 for logged in
- * users. uses the max-th entry for temporarily remembering a user
- * that, for examp., may not 'log in'.
- */
-
- LONG getumsg(pmsg, usrn, msgptr)
- MESSAGE *pmsg;
- COUNT usrn;
- TEXT *msgptr;
- {
- if (usrn >= 0)
- usr_to_ses[usrn] = (UTEXT) * ( ((UCOUNT *) msgptr) - 1 );
- if (usrn < usrmax)
- cpybuf(&usr_to_name[usrn*16], lastname, 16);
- return ((LONG) usr_to_ses[usrn]);
- }
-
- /*
- * if disconnect, call stop user
- */
-
- stpses(sesnum)
- UCOUNT sesnum;
- {
- FAST COUNT usrn;
-
- for (usrn = 0; usrn < usrmax; usrn++)
- if (sesnum == usr_to_ses[usrn]) {
- usr_to_ses[usrn] = NOT_A_SESN;
- stpusr(usrn);
- break;
- }
- }
-
- /*
- * when new user, stop previous login of same
- */
-
- stpname(name)
- TEXT * name;
- {
- FAST COUNT usrn;
-
- for (usrn = 0; usrn < usrmax; usrn++)
- if (NOT_A_SESN != usr_to_ses[usrn]
- && !strncmp(name, &usr_to_name[usrn*16], 16)) {
- usr_to_ses[usrn] = NOT_A_SESN;
- stpusr(usrn);
- break;
- }
- }
-
-
- COUNT dedusr(msgid)
- LONG msgid;
- {
- return(-1);
- }
-
- /*
- * wait for request from user
- */
-
- COUNT ctrqst(msgadr,pmsg)
- PFAST TEXT **msgadr; /* ptr to message area */
- MESSAGE *pmsg; /* ptr to message header */
- {
- static UCOUNT nexti = 0;
- FAST UCOUNT i;
- FAST UCOUNT j;
- FILEPARM *fpm;
-
- do {
- #ifndef FOREGROUND
- clear_task_events(); /* since going to poll all */
- #else
- if ((++kbcnt % KBFREQ) == 0 && kbhit())
- console_service();
- #endif
- /* check if a new session established
- * if so, mark in active table and restart listen
- */
-
- if (lstncb.f) {
- if (!lstncb.n.err)
- act_ses[lstncb.n.lsn] = 1;
- start_listen();
- idle = 0;
- }
-
- /*
- * see if any send's completed - send_done checks
- * for session lost and flags send buffer as free
- */
-
- for (i = 0; i < SRV_SNCBS; i++) {
- if (sncb[i]->f == 1) {
- idle = 0;
- send_done(i);
- }
- }
-
- /*
- * look for completed recv_anys - if error, then
- * it means a user has disconnected so update
- * active table - if no error then drop out of
- * this event poll loop with i indexing the recv
- * data. note: nexti is used because heavy traffic
- * might cause higher indexed buffers to never get
- * serviced if always started checking with 0-th.
- */
-
- for (i = nexti, j = 0; j < SRV_RNCBS; i++, j++) {
- if (i >= SRV_RNCBS)
- i = 0;
- if (rncb[i]->f == 1) {
- idle = 0;
- if (rncb[i]->n.err) {
- act_ses[rncb[i]->n.lsn] = 0;
- stpses(rncb[i]->n.lsn);
- start_recv(i);
- }
- else
- break;
- }
- }
- #ifndef FOREGROUND
- if (j == SRV_RNCBS)
- task_wait(0);
- #else
- if (++idle > STRETCH)
- dlaymos();
- #endif
- } while (j == SRV_RNCBS);
-
- /* a receive has completed */
-
- nexti = i; /* set next rncb to check */
-
- /* save the session number in hidden (to ctsrvr) part of
- * buffer in case ctsrvr wants to associate this session
- * with a user id
- */
-
- *( ((UCOUNT *) (*msgadr)) - 1 ) = (UCOUNT) rncb[i]->n.lsn;
-
- /* copy message to ctsrvr's buffer */
-
- cpybuf(*msgadr, rbuf[i], rncb[i]->n.buflen);
-
- /* restart recv_any */
-
- start_recv(i);
-
- /* copy to ctsrvr's msg header buffer */
-
- cpybuf(pmsg, *msgadr, sizeof(MESSAGE));
-
- /* got a message. if its a
- * login (TST_MSGSIZ), then the user's machine name has
- * been appended on the end by ctamsg. If so, use it to
- * search for duplicate user.
- */
-
- if (pmsg->mfunc == TST_MSGSIZ && pmsg->mdlen >= 16)
- {
- pmsg->mdlen -= 16;
- ((MESSAGE *)(*msgadr))->mdlen -=16;
- /* save name for later association with usrn in getumsg */
- cpybuf(lastname, *msgadr + sizeof(MESSAGE) + pmsg->mdlen, 16);
- stpname(lastname); /* kill any with same name */
- }
-
- /* check for file name conversion to absolute */
-
- if (pmsg->mfunc == FN_OPNFIL || pmsg->mfunc == FN_CREDAT ||
- pmsg->mfunc == FN_CREIDX || pmsg->mfunc == FN_CREMEM) {
- fpm = (FILEPARM *) (((TEXT *) *msgadr) + sizeof(MESSAGE));
- strcpy(ct_buf,fpm->fpnam);
- fulnam(fpm->fpnam,ct_buf,MAX_NAME);
- }
-
- return (NO_ERROR);
- }
-
- /*
- * send data to user
- */
-
- COUNT ctrspn(msgadr, pmsg, sizmsg, usrn)
- PFAST TEXT *msgadr;
- MESSAGE *pmsg;
- UCOUNT sizmsg;
- COUNT usrn;
- {
- FAST UCOUNT i;
- UCOUNT e;
- UTEXT sesn;
-
- if (usrn < 0) { /* signals a call from TST_STPUSR */
- usrn = - (usrn + 1);
- sesn = usr_to_ses[usrn];
- if (usrn < usrmax)
- usr_to_ses[usrn] = NOT_A_SESN; /* user logged out */
- }
- else {
- sesn = usr_to_ses[usrn];
- }
-
- cpybuf(msgadr, pmsg, sizeof(MESSAGE));
-
- /* wait for a free send buffer */
-
- do {
- for (i = 0; i < SRV_SNCBS; i++) {
- if (sncb[i]->f == 1)
- send_done(i);
- if (sncb[i]->f == 2)
- break;
- }
- #ifndef FOREGROUND
- if (i == SRV_SNCBS)
- task_wait(0); /* let others have cpu */
- #endif
- } while (i == SRV_SNCBS);
-
- cpybuf(sbuf[i], msgadr, sizmsg);
-
- sncb[i]->f = 0; /* flag in use and not done */
-
- /* start the send */
- e = nb_send(&sncb[i]->n,NCBanr,fanrf,sesn,sbuf[i],sizmsg);
-
- if (e)
- send_done(i);
-
- /* ???? */
- if (e) printf("\nSend error #%d (%dx)\n",e,e);
-
- return (e ? (uerr_cod = SRSP_ERR) : NO_ERROR);
- }
-
- /*
- * check status of user - return YES if session lost
- */
-
- COUNT norspn(usrn)
- COUNT usrn;
- {
- return NO; /* session lost always caught elsewhere */
- }
-
- /*
- * start asynchronous listen
- */
-
- start_listen()
- {
- lstncb.f = 0;
- nb_listen(&lstncb.n, NCBanr, fanrf, srvname, "*", NBRTO, NBSTO);
- }
-
- /*
- * start async receive using i-th recv ncb
- */
-
- start_recv(i)
- UCOUNT i;
- {
- rncb[i]->f = 0;
- nb_recvany(&rncb[i]->n, NCBanr, fanrf, namenum, rbuf[i], msgsiz);
- }
-
-
- /*
- * called when a send completes
- * set flag that send buffer is available
- */
-
- send_done(i)
- UCOUNT i;
- {
- if (sncb[i]->n.err != 0) /* if error then session lost */
- {
- act_ses[sncb[i]->n.lsn] = 0;
- stpses(sncb[i]->n.lsn);
- }
- sncb[i]->f = 2;
- }
-
-
- /*
- * close all sessions, cancel async commands and remove name from netbios
- */
-
- VOID far disconnect()
- {
- UCOUNT i;
-
- /* let any sends in progress finish */
-
- do {
- for (i = 0; i < SRV_SNCBS; i++) {
- if (sncb[i]->f == 0) {
- #ifndef FOREGROUND
- task_wait(0); /* sleep while waiting */
- #endif
- break;
- }
- }
- } while (i != SRV_SNCBS);
-
- /* wait for timeout, to make sure that not calling from
- * fanrf with sync nbios command
- */
-
- #ifndef FOREGROUND
- while (!task_wait(1))
- ;
- #endif
-
- /* cancel the async listen */
-
- if (lstncb.n.doneflag == 0xff) { /* if command was started */
- nb_cancel(&ncb.n, &lstncb.n);
- lstncb.n.doneflag = 0; /* in case disconnect called again */
- }
-
- /* close all active sessions */
-
- for (i=1; i<255; i++) {
- if (act_ses[i]) {
- act_ses[i] = 0;
- nb_hangup(&ncb.n, 0, fnulf, i);
- }
- }
-
- /* cancel all recv_any's in progress */
-
- for (i=0; i<SRV_RNCBS; i++) {
- if (rncb[i]->n.doneflag == 0xff) { /* if was started */
- nb_cancel(&ncb.n, &rncb[i]->n);
- rncb[i]->n.doneflag = 0; /* in case called again */
- }
- }
- if (namenum)
- nb_delname(&ncb.n, 0, fnulf, srvname);
- namenum = 0; /* in case called again */
- }
-
- chkusrtim(usrtim,usrmap,usrtrn)
- LONG *usrtim;
- COUNT *usrmap;
- LONG *usrtrn;
- {
-
- /* called from login */
- /* note, sessions lost & duplicate sessions caught elsewhere */
- return(NO_ERROR);
- }
-
-
- /*
- * rest of code for FOREGROUND
- */
-
- #ifdef FOREGROUND
-
- /*
- * called from ctnbios.c
- */
-
- UCOUNT far do_nb(ncb)
- NCB far *ncb;
- {
- union REGS r;
- struct SREGS sr;
-
- ncb->lana = 0; /* always adapter 0 */
-
- sr.es = sr.ds = (UCOUNT) ( ((ULONG) (NCB far *) ncb) >> 16 );
- r.x.bx = (UCOUNT) ncb;
- int86x(0x5c, &r, &r, &sr);
- return ((UCOUNT) r.h.al);
- }
-
-
-
- /*
- * dedicated server console routines
- */
-
- display_menu()
- {
- printf("\nDedicated server active\n");
- printf("\nStop or display Users (S or U)? ");
- }
-
- /* called when kbhit detected */
- console_service()
- {
- static COUNT pflg; /* flag if sub-func wants next char */
- static COUNT (*pfunc)(COUNT); /* addr of sub-func */
- COUNT c;
-
- COUNT stops(COUNT);
- COUNT display_users(COUNT);
-
- c = getche();
- printf("\n");
- if (pflg) {
- pflg = (*pfunc)(c);
- }
- else {
- switch (c) {
- /* note, all functions return !0 if they want the
- * next character
- */
- case 'S':
- case 's':
- pfunc = stops;
- pflg = stops(0);
- break;
- case 'U':
- case 'u':
- pfunc = display_users;
- pflg = display_users(0);
- break;
- default:
- printf("Unrecognized command\n");
- }
- }
- if (!pflg)
- display_menu();
- }
-
-
- COUNT stops(mode) /* returns != 0 if answer pending */
- COUNT mode; /* either 0 or answer to y/n */
- {
- FAST COUNT usrn;
- COUNT had = 0;
-
- if (!mode) {
- for (usrn = 0; usrn < usrmax; usrn++)
- if (NOT_A_SESN != usr_to_ses[usrn])
- had ++;
- if (had) {
- printf("%d users active ... are you sure? ",had);
- return (1);
- }
- }
- else {
- if (mode != 'y' && mode != 'Y')
- return (0);
- }
- if (stpsrv(0L,1,-1)) {
- printf("user has transaction in progress ... cannot stop\n");
- }
- else {
- ridmid();
- srvexit("Successful c-tree Termination",0,0);
- }
- return (0);
- }
-
- COUNT display_users(mode)
- COUNT mode; /* not used */
- {
- FAST COUNT usrn;
- COUNT had = 0;
- for (usrn = 0; usrn < usrmax; usrn++)
- if (NOT_A_SESN != usr_to_ses[usrn]) {
- printf("%.16s\n", &usr_to_name[usrn*16]);
- had ++;
- }
- if (!had)
- printf("No");
- else
- printf("%d", had);
- printf(" active users\n");
- return (0);
- }
-
- #endif
-
- /* end of ctsmsg.c */
-