/*                                                                              
  TCPECHOS ---/--+----- IUCV -----+---+---- NONE ----+---+---------+-<          
                 |                |   |              |   |         |            
                 '----- INET -----'   +---- POSIX ---+   '--DEBUG--'            
                                      |              |                          
                                      '----- MT -----'                          
To run:                                                                         
1. GLOBAL LOADLIB SCEERUN                                                       
2. TCPECHOS ....                                                                
                                                                                
To build:                                                                       
1. GLOBAL TXTLIB SCEELKED CMSLIB                                                
2. GLOBAL LOADLIB SCEERUN                                                       
3. c89 -W 0,SSCOMM //tcpecho.c -o //tcpecho -l //POSXSOCK -l //VMMTLIB          
*/                                                                              
/* #define _NO_PROTO */                                                         
#include "tcpecho.h"                                                            
                                                                                
int exitflag = 0;                                                               
                                                                                
static                                                                          
void* GetData( void *ns )                                                       
{                                                                               
 int rc, nbytes, socksize, offset, rcvlen, total;                               
 union {                                                                        
  struct sockaddr_iucv siucv;                                                   
  struct sockaddr_in sinet;                                                     
 } ClientSock;                                                                  
                                                                                
 struct {                                                                       
  char    userid[8];                                                            
  int     seqno;                                                                
  char    text[BUFFER_LEN];                                                     
 } buffer;                                                                      
                                                                                
 char  sure[] = "guaranteed";                                                   
 char  unsure[] = "suspect";                                                    
 char  vmuserid[9];                                                             
 char  *who, *where, *seclevel;                                                 
                                                                                
 printf("  Receiving data on fd %d\n", ns);                                     
 socksize = sizeof ClientSock;                                                  
 printf("  Getpeername\n");                                                     
 getpeername(ns, (struct sockaddr *)&ClientSock, &socksize);                    
 printf("  Got peername\n");                                                    
                                                                                
 if (ClientSock.siucv.siucv_family == AF_IUCV) {                                
/*    getpeeruserid(c, vmuserid); */                                            
   seclevel = sure;                                                             
   who = ClientSock.siucv.siucv_userid;                                         
   where = "\0";                                                                
 }else{                                                                         
   seclevel = unsure;                                                           
   who = buffer.userid;                                                         
   where = inet_ntoa( ClientSock.sinet.sin_addr );                              
 }                                                                              
                                                                                
 do {                                                                           
   offset = total = 0;                                                          
   rcvlen = sizeof buffer;                                                      
   do {                                                                         
 printf("  read(%d)\n", rcvlen);                                                
     nbytes = read(ns, (char *)(&buffer+offset), rcvlen);                       
     if ((nbytes < rcvlen) && (nbytes > 0) ) {                                  
       printf("    %d: From %.8s %s (%s): (partial data=%d)\n", ns,             
           who, where, seclevel, nbytes);                                       
       offset = offset + nbytes;                                                
       rcvlen = rcvlen - nbytes;                                                
     }                                                                          
     if (nbytes > 0)                                                            
       total = total + nbytes;                                                  
                                                                                
   } while ( (nbytes > 0) && (total < sizeof buffer));                          
                                                                                
   if (nbytes > 0) {                                                            
     printf("    %d: From %.8s %s (%s): %8d %s\n", ns,                          
           who, where, seclevel, buffer.seqno, buffer.text);                    
    if (strcmp(buffer.text, "*EXIT*") == 0) exitflag = 1;                       
   }                                                                            
 } while (nbytes > 0);                                                          
                                                                                
 if (nbytes < 0) {                                                              
   printf("read() for fd %d failed", ns);                                       
   perror("read()");                                                            
 }                                                                              
                                                                                
 rc = close(ns);                                                                
 if (rc < 0) {                                                                  
   printf("close() for fd %d failed", ns);                                      
   perror("close()");                                                           
 }                                                                              
                                                                                
 if (nbytes == 0)                                                               
   printf("  All data received on fd %d\n", ns);                                
                                                                                
 return NULL;                                                                   
}                                                                               
                                                                                
/*****************************************************************/             
/*****************************************************************/             
/**                                                             **/             
/**                        M A I N                              **/             
/**                                                             **/             
/*****************************************************************/             
/*****************************************************************/             
                                                                                
int main ( int argc, char *argv[])                                              
{                                                                               
 enum thread_values {NONE, MT, POSIX} thread_type = NONE;                       
 pthread_t ptid;                                                                
 int s, ns, rc,  re, tid, socktype = AF_IUCV, socksize;                         
 int dbg = 0;                                                                   
 union {                                                                        
  struct sockaddr_iucv siucv;                                                   
  struct sockaddr_in sinet;                                                     
 } mySock;                                                                      
                                                                                
                                                                                
 printf("ARGC = %d\n", argc);                                                   
 if (argc > 1 && strcmp(argv[1], "INET") == 0)                                  
   socktype = AF_INET;                                                          
                                                                                
 if (argc > 1 && strcmp(argv[1], "IUCV") == 0)                                  
   socktype = AF_IUCV;                                                          
                                                                                
 if (argc > 2 && strcmp(argv[2], "POSIX") == 0)                                 
   thread_type = POSIX;                                                         
                                                                                
 if (argc > 2 && strcmp(argv[2], "MT") == 0)                                    
   thread_type = MT;                                                            
                                                                                
 if (argc = 4 && strcmp(argv[3], "DEBUG") == 0)                                 
   dbg = 1;                                                                     
                                                                                
 s = socket(socktype, SOCK_STREAM, 0);                                          
 exit_if_error(Socket, s);                                                      
                                                                                
 Clear(mySock);                                                                 
                                                                                
 switch (socktype) {                                                            
   case AF_IUCV:                                                                
     printf("Using domain AF_IUCV\n");                                          
     socksize = sizeof mySock.siucv;                                            
                                                                                
     mySock.siucv.siucv_family = AF_IUCV;                                       
     memcpy( mySock.siucv.siucv_name, SERVER, 8);                               
     memset( mySock.siucv.siucv_nodeid, ' ', 8);                                
     break;                                                                     
                                                                                
   case AF_INET:                                                                
     printf("Using domain AF_INET\n");                                          
     socksize = sizeof mySock.sinet;                                            
                                                                                
     mySock.sinet.sin_family = AF_INET;                                         
     mySock.sinet.sin_addr.s_addr = INADDR_ANY;                                 
     mySock.sinet.sin_port = SERVER_PORT;                                       
     break;                                                                     
   default:                                                                     
     break;                                                                     
 }                                                                              
                                                                                
 if (dbg) printf("Binding...\n");                                               
 rc = bind(s, (struct sockaddr *)&mySock, socksize);                            
 if (dbg) printf("Bind RC=%d\n",rc);                                            
 exit_if_error(bind, rc);                                                       
 if (dbg) printf("Listening...\n");                                             
                                                                                
 rc = listen(s, 0);                                                             
 if (dbg) printf("Listen RC=%d\n", rc);                                         
 exit_if_error(listen, rc);                                                     
                                                                                
 while (!exitflag) {                                                            
   if (dbg) printf("Main(): Accept(%d,0,0) waiting...\n", s);                   
   ns = accept(s, 0, 0);                                                        
   exit_if_error(accept, ns);                                                   
                                                                                
   switch ( thread_type )                                                       
   {                                                                            
    case MT:                                                                    
      printf("Main(): Using ThreadCreate for fd %d\n", ns);                     
      ThreadCreate(&rc,&re,                                                     
                   &tid,                                                        
                   &rc,                                                         
                   0, 0,                                                        
                   (int)&GetData,                                               
                   (void *)ns,                                                  
                   1);                                                          
      exit_if_error(ThreadCreate, rc);                                          
      break;                                                                    
                                                                                
    case POSIX:                                                                 
      printf("Main(): Using pthread_create for fd %d\n", ns);                   
      rc = pthread_create(&ptid, NULL, GetData, (void *)ns);                    
      exit_if_error(pthread_create, rc);                                        
      break;                                                                    
                                                                                
    default:                                                                    
      printf("Using standard call for fd %d\n", ns);                            
      GetData( (void *)ns );                                                    
   }                                                                            
 }                                                                              
                                                                                
 rc = close(s);                                                                 
 exit_if_error(mainclose, rc);                                                  
                                                                                
 return(0);                                                                     
}