/* PEOPLE_TCP_Client.c */ /* Assignment 3 */ /* Modified by Lou Guzik IS2550 Summer 1997 */ /* http://www.pitt.edu/~lggst/ */ #define MOD_DATE "6-15-97" #include #include #include #include /* for kill, signal, and kill #defines */ #include /* for wait #defines */ #include #include /* for fstat function and macros*/ #include /* for the lockf function and macros */ #include /* for open function macros */ #include "myprotocol.h" extern int errno; extern char *sys_errlist[]; #define PAGE_LEN 15 #define BUFFER_FILE "buffer.tmp" void print_environ(); /*****************************/ /* Signal Handling Functions: Brian Antonishek (antonis@ctc.com) November 5, 1995 /*****************************/ void setSignalHandlers ( ); void handleSegViol ( ); void handleBusError ( ); void handleTrap ( ); void handleInterrupt ( ); void handleSignal ( ); /* GOBAL VARS */ int s = -1; /* socket */ FILE *handle; /* temp data file */ char delfile[SHORT_STRING]; char host[ SHORT_STRING ] = "icarus.lis.pitt.edu"; char service[ SHORT_STRING ] = "cs11"; /* "5011" */ int DEBUG = FALSE; int error; int IsConnected = FALSE; /*------------------------------------------------------------------ * main - PEOPLE_TCP: provides a lookup and data transfer *------------------------------------------------------------------ */ main( int argc, char *argv[] ) { char tmpstr[ SHORT_STRING ]; int params; setSignalHandlers (); strcpy( delfile, "rm -f " ); strcat( delfile, BUFFER_FILE ); params = 1; while( params != argc ) { if( strcmp(argv[params], "-d") == 0 || strcmp(argv[params], "-D") == 0 ) { DEBUG = TRUE; } else if( strcmp(argv[params], "-h") == 0 || strcmp(argv[params], "-H") == 0 ) { params++; if( params != argc ) strcpy( host, argv[params] ); else { printf( "ERROR: No Host Name Given ! \nExitting\n\n" ); exit( 1 ); } } else if( strcmp(argv[params], "-s") == 0 || strcmp(argv[params], "-S") == 0 ) { params++; if( params != argc ) strcpy( service, argv[params] ); else { printf( "ERROR: No Service Port Given ! \nExitting\n\n" ); exit( 1 ); } } params++; } /* while( params != argc ) */ if( DEBUG ) displayparms( argc, argv ); /* DRAW THE MENU */ while( TRUE ) { printf("\n\n\n\n\n\n\n\n\n\n\n\n"); system( "clear" ); printf( "\t\t Lou Guzik's People Client Server Menu \n\n" ); printf( "Connection=" ); if( IsConnected ) printf("TRUE" ); else printf("FALSE" ); printf(" Socket=%d Host=%s Service=%s Debug=", s, host, service ); if( DEBUG ) printf("ON \n\n" ); else printf("OFF \n\n" ); printf( "\t\t\t ?) About \n\n" ); printf( "\t\t\t C)onnect \n" ); printf( "\t\t\t U)nconnect \n\n" ); printf( "\t\t\t A)dd \n" ); printf( "\t\t\t B)rief \n" ); printf( "\t\t\t F)ind \n" ); printf( "\t\t\t G)et full report \n\n" ); printf( "\t\t\t E)nviroment Vars\n" ); printf( "\t\t\t H)ost \n" ); printf( "\t\t\t P)arameter Display \n" ); printf( "\t\t\t S)ervice \n" ); printf( "\t\t\t T)oggle Debug \n" ); printf( "\t\t\t Q)uit \n" ); printf( "\n Enter Selection ==> " ); gets( tmpstr ); printf(" \n" ); if( DEBUG ) displayparms( argc, argv ); tmpstr[0] = toupper(tmpstr[0]); switch( tmpstr[0] ) { case '?': /* ABOUT */ help(); pause(); break; case 'C': if( IsConnected ) printf( "Already connected\n"); else { printf( "Trying to Connect to Host %s %s... \n", host, service ); s = connectTCP(host, service); IsConnected = TRUE; } pause(); /* CONNECT */ break; case 'U': /* UNCONNECT */ if( IsConnected ) { printf( "Unconnecting to Host %s %s... \n", host, service ); TCPexchange(host, service, TERMINATE ); close( s ); s = -1; IsConnected = FALSE; } else printf( "Already unconnected\n"); pause(); break; case 'A': /* ADD */ TCPexchange(host, service, ADD ); pause(); break; case 'B': /* BRIEF */ TCPexchange(host, service, BRIEF ); pause(); break; case 'F': /* FIND */ TCPexchange(host, service, FIND ); pause(); break; case 'G': /* GET FULL */ TCPexchange(host, service, FULL ); pause(); break; case 'T': /* TOGGLE */ if( DEBUG ) { DEBUG = FALSE; printf( "DEBUG is OFF \n" ); } else { DEBUG = TRUE; printf( "DEBUG is ON \n" ); } pause(); break; case 'E': print_environ(); break; case 'H': if( IsConnected ) printf( "Can NOT change Host while connected\n"); else { printf(" Old Host Name = %s \nEnter New Host Name =>", host ); gets( tmpstr ); if( tmpstr[0] != '\0' ) strcpy( host, tmpstr ); printf( "\nNew Host Name = %s \n", host ); } pause(); break; case 'S': if( IsConnected ) printf( "Can NOT change Service while connected\n"); else { printf(" Old Service Port = %s \nEnter New Service Port =>", service ); gets( tmpstr ); if( tmpstr[0] != '\0' ) strcpy( service, tmpstr ); printf( "\nNew Service Port = %s \n", service ); } pause(); break; case 'P': displayparms( argc, argv ); printf( "DEBUG = " ); if( DEBUG ) printf( "ON \n" ); else printf( "OFF \n" ); pause(); break; case 'Q': if( IsConnected ) { printf("\tPlease Unconnect first before exitting!\n" ); pause(); break; } else { printf( "Quitting\n\n" ); goto LEAVE; } default: printf(""); } } /* while( TRUE ) */ LEAVE: exit( 0 ); } /* main( int argc, char *argv[] ) */ /*-------------------------------------------------------------------- * PAUSE() *-------------------------------------------------------------------- */ pause() { char tmp[64]; printf( "\nPress to Continue. " ); gets( tmp ); } /*-------------------------------------------------------------------- * PRINT_ENVIRON() * /home3/icarus.lis/misc/mbsclass/i2550/Resources/Unix *-------------------------------------------------------------------- */ void print_environ() { extern char ** environ; char *evar, *eval; int i; printf("%20s%-59.59s\n","Environment Variable","Value"); for (i=0;environ[i]!=NULL; i++) { evar=environ[i];/* establish a pointer to the beginning of the string */ eval=strchr(environ[i], '='); /* get the location of the = sign */ *eval=0; /* null terminate the first part of the string */ eval++; /* increment it by 1 to point at the value */ printf("%20s %-59.59s\n", evar,eval); if( (i>0) && ((i%PAGE_LEN)==0) ) pause(); } } /*-------------------------------------------------------------------- * DISPLAYPARMS() *-------------------------------------------------------------------- */ displayparms( int argc, char *argv[] ) { int i; printf("argc=%d", argc); for (i=0; i by itself while changing Host or Service, \n" ); printf( "will abort the change. \n" ); } /*-------------------------------------------------------------------- * TCPexchange() - send input to people service on host and print * the reply. *-------------------------------------------------------------------- */ int TCPexchange( char *host, char *service, int Mode ) { /* buffer for line of text */ char name[SHORT_STRING], buf[MAX_STRING], temp[MAX_STRING]; int i; int n; /* read count */ int loop; time_t now; int newlines = 0; char ch; struct Msg inmsg, outmsg; int flag; /* CHECK FOR CONNECTION BEFORE DOING ANY OPERATIONS */ if( ! IsConnected ) { printf("\t Please make a connection first! \n" ); return( 5 ); } inmsg.mode = 0; inmsg.len = 0; inmsg.data[0] = 0; outmsg.mode = Mode; outmsg.len = 0; outmsg.data[0] = 0; /****************************************************************************************** STOP AND WAIT PROTOCOL ******************************************************************************************/ switch( Mode ) { case BRIEF: case FULL: /* OPEN UP TEMP FILE FOR DATA STORAGE */ if ( (handle = fopen( BUFFER_FILE, "w+" )) == NULL) { printf( "\nError Creating TCPexchance() %s file !\n", BUFFER_FILE ); return 1; } if( DEBUG ) { printf( "TCPex(b/f-1) write to s=>%d<= outmsg=>%d %d %s<= \n", s, outmsg.mode, outmsg.len, outmsg.data ); /* pause(); */ } /* SEND OPERATION REQUEST TO SERVER */ write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len) ); /* RECEIVE RESPONCE TO REQUEST FROM SERVER, ASSUME THAT 2 BYTES WILL BE READ */ n = read( s, &inmsg, sizeof(inmsg.mode)+sizeof(inmsg.len) ); if( DEBUG ) { printf( "TCPex(b/f-2) read of s=>%d<= n=%d inmsg=>%d %d %s<= \n", s, n, inmsg.mode, inmsg.len, inmsg.data ); pause(); } if(n < 0) errexit("socket read failed: %s\n",sys_errlist[errno]); flag = TRUE; while( flag ) { if( inmsg.mode == (REPLY+BRIEF+FULL) ) { /* COLLECT ALL THE DATA SENT IN THIS PACKET */ i = 0; while( i < inmsg.len ) { n = read( s, buf+i, MAX_STRING ); if( DEBUG ) { buf[ i+n ] = 0; printf( "TCPex(b/f-3) read of s=>%d<= i=%d n=%d buf=>%s<= \n", s, i, n, buf ); /* pause(); */ } if(n < 0) errexit("socket read failed: %s\n",sys_errlist[errno]); i += n; } buf[ i ] = 0; /* SAVE TO FILE, FASTER THAN CONSOLE I/O */ fprintf( handle, "%s", buf ); /* SEND OK TO SERVER TO SEND DATA */ outmsg.mode = OK + BRIEF + FULL; outmsg.len = 0; outmsg.data[0] = 0; write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len) ); /* RECEIVE THE NEXT PACKET FROM SERVER */ n = read( s, &inmsg, sizeof(inmsg.mode)+sizeof(inmsg.len) ); if( DEBUG ) { printf( "TCPex(b/f-4) read of s=>%d<= n=%d inmsg=>%d %d<= \n", s, n, inmsg.mode, inmsg.len ); /* pause(); */ } if(n < 0) errexit("socket read failed: %s\n",sys_errlist[errno]); } /* if( inmsg.mode == REPLY ) */ /* END OF SENT DATA HAS BEEN REACHED */ else if( inmsg.mode == (END_DATA+BRIEF+FULL) ) { flag = FALSE; fseek( handle, 0L, SEEK_SET ); /* PRINT OUT THE FILE THAT HAS THE SAVE DATA */ while(TRUE) { ch = fgetc(handle); if( ch == EOF ) break; putchar( ch ); if( ch == '\n' ) newlines++; if( newlines == PAGE_LEN ) { pause(); newlines = 0; } } } /* SERVER HAS SENT A TERMINATE, SERVER MAY HAVE BEEN KILLED */ else if( inmsg.mode == TERMINATE ) { flag = FALSE; printf("\n\t Recieved a Terminate from server, closing socket\n" ); pause(); close( s ); s = -1; IsConnected = FALSE; } /* AN UNKNOWN OPERATION HAS BEEN RECIEVED */ else { flag = FALSE; printf("\n\t Recieved a Unknown Operation from server, closing socket\n" ); close( s ); s = -1; IsConnected = FALSE; } } /* while( flag ) */ /* DEALLOCATE FILE RESOURCE */ fclose( handle ); system( delfile ); break; /* End of case BRIEF: case FULL: */ case FIND: /* OPEN UP TEMP FILE FOR DATA STORAGE */ if ( (handle = fopen( BUFFER_FILE, "w+" )) == NULL) { printf( "\nError Creating TCPexchance() %s file !\n", BUFFER_FILE ); return 1; } if( DEBUG ) { printf( "TCPex(find-1) write to s=>%d<= outmsg=>%d %d %s<= \n", s, outmsg.mode, outmsg.len, outmsg.data ); /* pause(); */ } /* SEND OPERATION REQUEST TO SERVER */ write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len) ); /* RECEIVE RESPONCE TO REQUEST FROM SERVER, ASSUME THAT 2 BYTES WILL BE READ */ n = read( s, &inmsg, sizeof(inmsg.mode)+sizeof(inmsg.len) ); if( DEBUG ) { printf( "TCPex(find-2) read of s=>%d<= n=%d inmsg=>%d %d %s<= \n", s, n, inmsg.mode, inmsg.len, inmsg.data ); pause(); } if(n < 0) errexit("socket read failed: %s\n",sys_errlist[errno]); if( inmsg.mode == REPLY+FIND ) { if( inmsg.len == 0 ) { outmsg.mode = END_DATA+FIND; outmsg.len = 0; write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len ) ); printf("Sorry, there are no records to search for \n" ); fclose( handle ); pause(); break; } again: printf("Contact numbers are between 1 and %d \n", inmsg.len ); printf("Please enter a contact number to \n" ); printf("find or enter zero to cancel ===>" ); gets( buf ); i = atoi( buf ); printf("\n"); if( i > inmsg.len || i < 0 ) goto again; if( i == 0 ) { fclose( handle ); outmsg.mode = END_DATA+FIND; outmsg.len = 0; write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len ) ); printf("Cancelling Find! \n" ); break; } outmsg.mode = FIND+OK; outmsg.len = i; if( DEBUG ) { printf( "TCPex(find-2b) write to s=>%d<= outmsg=>%d %d %s<= \n", s, outmsg.mode, outmsg.len, outmsg.data ); /* pause(); */ } write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len) ); for( loop=0; loop<4; loop++ ) { /* COLLECT ALL THE DATA SENT IN THIS PACKET */ n = read( s, &inmsg, sizeof(inmsg.mode)+sizeof(inmsg.len) ); if( DEBUG ) { printf( "TCPex(find-3) read of s=>%d<= n=%d inmsg=>%d %d %s<= \n", s, n, inmsg.mode, inmsg.len, inmsg.data ); pause(); } if(n < 0) errexit("socket read failed: %s\n",sys_errlist[errno]); i = 0; while( i < inmsg.len ) { n = read( s, buf+i, MAX_STRING ); if( inmsg.mode == TERMINATE ) { flag = FALSE; printf("\n\t Recieved a Terminate from server, closing socket\n" ); fclose( handle ); close( s ); s = -1; IsConnected = FALSE; fclose( handle ); return( 1 ); } /* AN UNKNOWN OPERATION HAS BEEN RECIEVED */ else if( inmsg.mode == TERMINATE ) { flag = FALSE; printf("\n\t Recieved a Unknown Operation from server, closing socket\n" ); close( s ); s = -1; IsConnected = FALSE; fclose( handle ); return( 1 ); } if( DEBUG ) { buf[ n ] = 0; printf( "TCPex(find-4) read of s=>%d<= i=%d n=%d buf=>%s<= \n", s, i, n, buf ); /* pause(); */ } if(n < 0) errexit("socket read failed: %s\n",sys_errlist[errno]); i += n; } /* while( i < inmsg.len ) */ buf[ i ] = 0; /* SAVE TO FILE, FASTER THAN CONSOLE I/O */ fprintf( handle, "%s", buf ); /* SEND OK TO SERVER TO SEND DATA */ outmsg.mode = OK + FIND; outmsg.len = 0; outmsg.data[0] = 0; write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len) ); } /* for( loop=0; loop<4; loop++ ) */ /* PRINT OUT THE FILE THAT HAS THE SAVE DATA */ fseek( handle, 0L, SEEK_SET ); while(TRUE) { ch = fgetc(handle); if( ch == EOF ) break; putchar( ch ); } fclose( handle ); } /* if( inmsg.mode == REPLY ) */ /* SERVER HAS SENT A TERMINATE, SERVER MAY HAVE BEEN KILLED */ else if( inmsg.mode == TERMINATE ) { flag = FALSE; printf("\n\t Recieved a Terminate from server, closing socket\n" ); fclose( handle ); close( s ); s = -1; IsConnected = FALSE; } /* AN UNKNOWN OPERATION HAS BEEN RECIEVED */ else { flag = FALSE; printf("\n\t Recieved a Unknown Operation from server, closing socket\n" ); close( s ); s = -1; IsConnected = FALSE; } break; /* End of case FIND: */ case ADD: printf("Press to abort\n"); printf("Enter your full name: "); fgets(name,sizeof(name),stdin); /* REMOVE THE NEWLINE CHARATER */ name[strlen(name)-1]=0; if( name[0] == NULL ) { printf("\nAdd aborted!\n" ); break; } now=time(NULL); strcpy(temp,ctime(&now)); temp[strlen(temp)-1]=0; sprintf(outmsg.data, "%s\n\tcheck in at %s \n\tUser name = %s \n\tDisplay = %s\n", name, temp, getenv("USER"), getenv("DISPLAY")); outmsg.len = strlen( outmsg.data ); if( DEBUG ) printf( "TCPex(add-1) write to s=>%d<= outmsg=>%d %d %s<= \n", s, outmsg.mode, outmsg.len, outmsg.data ); write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len)+outmsg.len ); break; /* End of case ADD: */ case TERMINATE: write( s, &outmsg, sizeof(outmsg.mode)+sizeof(outmsg.len ) ); break; default: printf("Client in TCPexchange, unknown Menu Selection=%d\n", Mode ); } /* switch( Mode ) */ return 0; } /* int TCPexchange( char *host, char *service, int Mode ) */ /******************************************************************************************/ /**********************************************/ /* setSignalHandlers() - /**********************************************/ void setSignalHandlers() { /* SIGs from /usr/include/sys/signal.h */ /* Handle someone interrupting */ signal(SIGINT,handleInterrupt); /* interrupt (rubout) */ /* * Handle New Programming * Features... :-) */ signal (SIGSEGV, handleSegViol); /* segmentation violation */ signal (SIGBUS, handleBusError); /* bus error */ signal (SIGTRAP, handleTrap); /* trace trap (not reset when caught) */ /* Handle Misc. Signals */ signal(SIGHUP,handleSignal); /* hangup */ signal(SIGQUIT,handleSignal); /* quit (ASCII FS) */ signal(SIGTERM,handleSignal); /* software termination signal from kill */ } /**********************************************/ /* handleSegViol() - segmentation violation /**********************************************/ void handleSegViol() { int buf[2]; fprintf(stderr, "\n\nClient got a SEG VIOLATE signal to exit. socket=%d ", s ); fprintf(stderr, "\nWill try to Close data file & Clean up \n\n"); /* Close Log file & Clean up */ buf[0] = TERMINATE; buf[1] = 0; write( s, buf, sizeof(buf) ); /* DEALLOCATE SOCKET AS SOON AS POSSIBLE */ close( s ); /* DEALLOCATE FILE RESOURCE */ fclose( handle ); /* system( delfile ); */ /* Signal will be considered 'handled' so * set default signal handler and raise another signal */ signal (SIGSEGV, SIG_DFL); /* set default seg. viol. handler */ kill (getpid (), SIGSEGV); return; } /**********************************************/ /* handleBusError() - /**********************************************/ void handleBusError() { int buf[2]; fprintf(stderr, "\n\nClient got a BUS ERROR signal to exit. socket=%d ", s ); fprintf(stderr, "\nWill try to Close data file & Clean up \n\n"); /* Close Log file & Clean up */ buf[0] = TERMINATE; buf[1] = 0; write( s, buf, sizeof(buf) ); /* DEALLOCATE SOCKET AS SOON AS POSSIBLE */ close( s ); /* DEALLOCATE FILE RESOURCE */ fclose( handle ); /* system( delfile ); */ /* Signal will be considered 'handled' so * set default signal handler and raise another signal */ signal (SIGBUS, SIG_DFL); /* set default bus error handler */ kill (getpid (), SIGBUS); return; } /**********************************************/ /* handleTrap() - trace trap /**********************************************/ void handleTrap() { int buf[2]; fprintf(stderr, "\n\nClient got a TRAP signal to exit. socket=%d ", s ); fprintf(stderr, "\nWill try to Close data file & Clean up \n\n"); /* Close Log file & Clean up */ buf[0] = TERMINATE; buf[1] = 0; write( s, buf, sizeof(buf) ); /* DEALLOCATE SOCKET AS SOON AS POSSIBLE */ close( s ); /* DEALLOCATE FILE RESOURCE */ fclose( handle ); /* system( delfile ); */ /* System doesn't unset this signal after we handle it * so let system handle it with its normal process, * no need to raise it again. */ signal (SIGTRAP, SIG_DFL); /* set default trace trap handler */ return; } /**********************************************/ /* handleInterrupt() - /**********************************************/ void handleInterrupt() { fprintf(stderr, "\n\n You can NOT out of program if connected to socket! \n\n Press to continue."); } /**********************************************/ /* handleSignal() - /**********************************************/ void handleSignal() { int buf[2]; fprintf(stderr, "\n\nClient got a signal to exit. socket=%d ", s ); fprintf(stderr, "\nWill try to Close data file & Clean up \n\n"); if( DEBUG ) /* Close Log file & Clean up */ buf[0] = TERMINATE; buf[1] = 0; write( s, buf, sizeof(buf) ); /* DEALLOCATE SOCKET AS SOON AS POSSIBLE */ close( s ); /* DEALLOCATE FILE RESOURCE */ fclose( handle ); /* system( delfile ); */ /* Now exit. */ exit(0); }