/* 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; int main ( int argc, char *argv[]) { enum thread_values {NONE, MT, POSIX} thread_type = NONE; pthread_t ptid; int s, c, rc, re, tid, socktype = AF_IUCV, socksize; int dbg = 0; union { struct sockaddr_iucv siucv; struct sockaddr_in sinet; } mySock; void GetData (void *); if (argc > 1 && strcmp(argv[1], kINET) == 0) socktype = AF_INET; 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; } rc = bind(s, (struct sockaddr *)&mySock, socksize); exit_if_error(bind, rc); if (dbg) printf("Listening...\n"); rc = listen(s, 0); exit_if_error(listen, rc); while (!exitflag) { if (dbg) printf("Main(): Accept(%d,0,0) waiting...\n", s); c = accept(s, 0, 0); exit_if_error(accept, c); switch ( thread_type ) { case MT: printf("Main(): Using ThreadCreate for fd %d\n", c); ThreadCreate(&rc,&re, &tid, &rc, 0, 0, (int)GetData, (void *)c, 1); exit_if_error(ThreadCreate, rc); break; case POSIX: printf("Main(): Using pthread_create for fd %d\n", c); rc = pthread_create(&ptid, NULL, (void *)GetData, (void *)c); exit_if_error(pthread_create, rc); break; default: printf("Using standard call for fd %d\n", c); GetData( (void *)c ); } } rc = close(s); exit_if_error(mainclose, rc); return(0); } void GetData( void *c ) { 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", c); socksize = sizeof ClientSock; getpeername(c, (struct sockaddr *)&ClientSock, &socksize); if (ClientSock.siucv.siucv_family == AF_IUCV) { getpeeruserid(c, vmuserid); seclevel = sure; who = vmuserid; where = "\0"; }else{ seclevel = unsure; who = buffer.userid; where = inet_ntoa( ClientSock.sinet.sin_addr ); } do { offset = total = 0; rcvlen = sizeof buffer; do { nbytes = read(c, (char *)(&buffer+offset), rcvlen); if ((nbytes < rcvlen) && (nbytes > 0) ) { printf(" %d: From %.8s %s (%s): (partial data=%d)\n", c, 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", c, 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", c); perror("read()"); } rc = close(c); if (rc < 0) { printf("close() for fd %d failed", c); perror("close()"); } if (nbytes == 0) printf(" All data received on fd %d\n", c); return; }