bunfigs
Figure 1.  Initialize NetBios Driver 
 
  /*--------------------------------------------------------* 
   * Initialize NetBios driver by getting its name, through * 
   * NetBiosEnum() and opening it with NetBiosOpen()        * 
   *--------------------------------------------------------*/ 
  InitializeNetbios(WORD *devHandle) 
  { 
    int ccode; 
    struct netbios_info_1 NB_INFO; 
    unsigned int totEntries, numEntries; 
 
    if (ccode = NetBiosEnum((char far *)"", 1,  
                (char far *)&NB_INFO, 
                (unsigned)sizeof(NB_INFO),  
                (unsigned short far *)&numEntries, 
                (unsigned short far *)&totEntries)) 
        printf("Error occurred during NetBiosEnum: %x\n", ccode); 
    if (ccode = NetBiosOpen((char far *)NB_INFO.nb1_driver_name,  
               (char far *)0, (unsigned)NB_REGULAR, 
               (unsigned short far *)devHandle)) 
        printf("Error occurred during NetBiosOpen: %x.\n", ccode); 
  } Figure 2.  Adding a name via the thread AddServerName. 
 
 LONG    wait_sem_val = 0; 
 HSEM    wait_sem = &wait_sem_val; 
  
 main() 
 { 
 . . . . 
    DosSemSet(wait_sem); 
    stackPtr = (WORD far *) malloc(1024) + (1024 / sizeof(WORD)); 
    ccode = DosCreateThread(AddServerName, &addNameThreadID, (char far *)stackPtr); 
    if (ccode) 
        printf("DosCreateThread Error : %d\n", ccode); 
        . . . .  
    DosSemWait(wait_sem, -1L);        /* wait for the name to be added */ 
} 
 
  /*------------------------------------------------------------------------* 
   * AddServerName adds the servers name, clearing the wait_sem when done.  * 
   * It kills itself upon termination, if an error occurs it kills everyone * 
   *------------------------------------------------------------------------*/ 
  void far AddServerName() 
  { 
   if (!AddName(SERVER_NAME, devHandle)) { 
        DeleteName(SERVER_NAME, devHandle); 
        if (!AddName(SERVER_NAME, devHandle)) { 
            DosSemClear(wait_sem); 
            printf("\nError in NetBios, could't add name"); 
            DosExit (1, 0); 
        } 
    } 
    DosSemClear(wait_sem); 
    DosExit (0, 0); 
  } 
 
  /*------------------------------------------------*/ 
  AddName(char *name, WORD devHandle) 
  { 
    NCB addNCB; 
 
    memset((char *)&addNCB, '\0', 64); 
    addNCB.ncb_command = NCBADDNAME; 
    addNCB.ncb_lana_num = 0x00; 
    memcpy(addNCB.ncb_name, name, strlen(name)); 
    if (NetBiosSubmit(devHandle, SINGLE_RETRY, &addNCB)) 
        return(FALSE); 
    else 
        return (TRUE); 
} Figure 3.  Cloned communications function. 

/*----------------------------------------------------------------------* 
 * Receiver is the server side of the IPC connection.  It makes, reads, * 
 * writes, and closes the pipe until 'down' is entered.                 * 
 *----------------------------------------------------------------------*/ 
void far Receiver(int clientNum) 
{ 
    COMMBUFFER commBuffer; 
    int ccode; 
 
    DosSemWait(wait_sem, -1L);          /* wait for name to be added */ 
    do { 
        ListenForClient(&sessionNum[clientNum]); 
        do { 
            DoReceive((char *)&commBuffer, sizeof(COMMBUFFER), 
                   sessionNum[clientNum], devHandle, &ncb[clientNum]); 
            if (!TLAServiceRequest(&commBuffer)) 
                strcpy(commBuffer.record.explain, 
                              "The TLA requested could not be found."); 
            DoSend((char *)&commBuffer, sizeof(COMMBUFFER), 
                   sessionNum[clientNum], devHandle, &ncb[clientNum]); 
            if (commBuffer.lastOne) 
                break; 
        } while (TRUE); 
        /* client hangs up, so we don't have to */ 
        sessionNum[clientNum] = 0; 
    } while (TRUE); 
} 
Figure 4.  NetBios Listen command. 
 
/*----------------------------------------------------------------------* 
 * Listen for someone to call us, don't return until we've been called  * 
 *----------------------------------------------------------------------*/ 
ListenForClient(int *sessionNum) 
{ 
    int ccode; 
    NCB listenNCB; 
 
    memset((char *)&listenNCB, '\0', 64); 
    listenNCB.ncb_command = NCBLISTEN | ASYNCH; 
    strcpy(listenNCB.ncb_callname, "*"); 
    strcpy(listenNCB.ncb_name, SERVER_NAME); 
    listenNCB.ncb_lana_num = 0x00; 
    listenNCB.ncb_rto = 0x30; 
    listenNCB.ncb_sto = 0x10; 
 
    if (ccode = NetBiosSubmit(devHandle, SINGLE_RETRY, &listenNCB)) 
        printf("NCB Submit error. ccode = %x.\n", ccode); 
    while (listenNCB.ncb_cmd_cplt == 0xFF); 
    if (listenNCB.ncb_cmd_cplt == 0) 
        *sessionNum = listenNCB.ncb_lsn; 
} 
Figure 5.  NetBios commands Send and Receive. 
 
/*--------------------------------------------------------*/ 
DoSend(char *buffer, int size, int sessionNum,  
       WORD devHandle, NCB *ncb) 
{ 
    int ccode; 
    NCB sendNCB; 
 
    memset( (char *)ncb, '\0', 64 ); 
    ncb->ncb_command = NCBSEND; 
    ncb->ncb_lana_num = 0; 
    ncb->ncb_lsn = sessionNum; 
    ncb->ncb_length = size; 
    ncb->ncb_buffer = buffer; 
    if (ccode = NetBiosSubmit(devHandle, SINGLE_RETRY, ncb)) { 
        printf("Error sending, submit error: %x\n", ccode); 
        return (FALSE); 
      } 
    return (TRUE); 
} 
 
/*--------------------------------------------------------*/ 
DoReceive(char *buffer, int length, int sessionNum,  
          WORD devHandle, NCB *ncb) 
{ 
    int ccode; 
 
    memset( (char *)ncb, '\0', 64 ); 
    ncb->ncb_command = NCBRECV; 
    ncb->ncb_lana_num = 0; 
    ncb->ncb_lsn = sessionNum; 
    ncb->ncb_length = length; 
    ncb->ncb_buffer = buffer; 
    if (ccode = NetBiosSubmit(devHandle, SINGLE_RETRY, ncb)) { 
        printf("\nError receiving, submit error: %x\n", ccode); 
        return (FALSE); 
    } 
    return (TRUE); 
}Figure 6.  Close NetBios down. 
 
 /*--------------------------------------------------------* 
 * CleanUp performs the exiting procedures, disconnecting * 
 * and closing open sessions.                             *                                                   
       * 
 *--------------------------------------------------------*/ 
CleanUp() 
{ 
    int ccode; 
    int i; 
    char response[20]; 
 
    /*  wait until 'down' is indicated  */ 
    do { 
        scanf("%s", response); 
    } while (strcmp(response, "down") != 0); 
    DosEnterCritSec(); 
    TLACloseIndex(); 
    for (i = 0; i < CLIENT_NUM; i++) { 
        if (sessionNum[i] != 0) { 
            CancelNCB(ncb[i]);     /* cancel outstanding NCB */ 
            DoHangUp(sessionNum[i]); 
        } 
    } 
    DeleteName(SERVER_NAME, devHandle); 
    if (ccode = NetBiosClose(devHandle, (int)0)) 
        printf("Error occurred during NetBiosClose. ccode = %x\n"); 
    DosExit(1, 0); 
    DosExitCritSec(); 
} 
 
Figure 7.  NetBios Call command 
 
/*------------------------------------------------------*/ 
DoCall(char *callName, WORD devHandle, int *sessionNum,  
       char *yourName) 
{ 
    NCB callNCB; 
    int ccode; 
 
    memset((char *)&callNCB, '\0', 64); 
    callNCB.ncb_command = NCBCALL; 
    callNCB.ncb_lana_num = 0; 
    callNCB.ncb_rto = 0x10; 
    callNCB.ncb_sto = 0x10; 
    memcpy(callNCB.ncb_callname, callName, strlen(callName)); 
    memcpy(callNCB.ncb_name, yourName, strlen(yourName)); 
    if (ccode = NetBiosSubmit(devHandle, SINGLE_RETRY, &callNCB)) 
        printf("Error calling. NCB Submit error # %x\n", ccode); 
 
   if (callNCB.ncb_cmd_cplt != 0) { 
       printf("\tError in CALL command: %x\n", callNCB.ncb_cmd_cplt); 
       return (FALSE);  
   } 
   *sessionNum = callNCB.ncb_lsn; 
   return (TRUE); 
} Figure 8.  Commbuffer description. 
 
/* record structure, external data file is a list of these */ 
/* structures, does not have to be sorted                  */ 
typedef struct { 
    char tla[10];      /* the tla of record */ 
    USHORT offset;     /* offset of next record with this TLA */ 
    char expanded[80]; /* the expanded tla */ 
    char explain[160]; /* an explanation of the tla */ 
} RECORD; 
 
/* communication buffer passed into the server module */ 
typedef struct { 
    int type;                /* type of communication - see types below */ 
    RECORD record;           /* information offered */ 
    int lastOne;             /* are there any more requests on this session */ 
} COMMBUFFER;  
 
/* Types of requests that come to server */ 
#define ADD_TO_LIST       0x0001    /* add new tla */ 
#define QUERY             0x0002    /* query to get expanded string only */ 
#define SORT              0x0004    /* sort file and create new index */ 
 
