Advertisement
AnonymousNamefag

client.c

Oct 10th, 2018
107
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <sys/stat.h>
  4. #include <stdlib.h>
  5. #include <sys/ipc.h>
  6. #include <sys/shm.h>
  7. #include <sys/msg.h>
  8. #include <termios.h>
  9. #include <signal.h>
  10. #include <proc/procps.h>
  11.  
  12. #include "chat.h"
  13.  
  14. char nick[10];
  15. pid_t pid;
  16.  
  17. struct termios term;
  18. struct termios save;
  19.  
  20. int main( int argc, char **argv ){
  21.     signals();
  22.     register_shared_memory();
  23.     register_message_queue();
  24.     enter_raw_mode();
  25.     setup_user();
  26.     input_loop();
  27.     exit_raw_mode();
  28.     return 0;
  29. }
  30.  
  31. void signals(){
  32.     signal( SIGTSTP, stop );
  33.     signal( SIGINT, quit );
  34.     signal( SIGTERM, quit );
  35.     signal( SIGCONT, cont );
  36.     signal( SIGPOLL, client_process );
  37. }
  38.  
  39. void stop( int signo ){
  40.     tcsetattr( 0, TCSANOW, &save );
  41.     raise( SIGSTOP );
  42. }
  43.  
  44. void cont( int signo ){
  45.     tcsetattr( 0, TCSANOW, &term );
  46. }
  47.  
  48. void quit( int signo ){
  49.     tcsetattr( 0, TCSANOW, &save );
  50.     exit( 0 );
  51. }
  52.  
  53. void setup_user( void ){
  54.     pid = getpid();
  55.     struct message *msg;
  56.     msg->mtype = pid;
  57.     msg->mtext = "JOIN\n";
  58.     msgsnd( msg_id, msg, 4096, 0 );
  59.     msgrcv( msg_id, msg, 4096, SERVER_MESSAGE_TYPE + pid, 0 );
  60.     mwrite( msg );
  61.     tcsetattr( 0, TCSANOW, &save );
  62.     fgets( nick, 10, stdin );
  63.     /* Will fgets() work in raw mode? */
  64.     tcsetattr( 0, TCSAFLUSH, &term );
  65.     msg->mtext = nick;
  66.     msgsnd( msg_id, msg, 4096, 0 );
  67.     msgrcv( msg_id, msg, 4096, SERVER_MESSAGE_TYPE + pid, 0 );
  68.     mwrite( msg );
  69. }
  70.  
  71. void input_loop(){
  72.     struct message *msg;
  73.     msg->mtype = pid;
  74.     char buf[4092]; /* Size is 4 bytes less to prevent buffer overflows. */
  75.     for(;;){
  76.         fgets( buf, 4092, stdin );
  77.         if( !strncmp( buf, "bye\n", 4 ) ){
  78.             msg->mtext = "BYE\n";
  79.         }
  80.         else{
  81.             sprintf( msg->mtext, "SAY %s", buf );
  82.         }
  83.         msgsnd( msg_id, msg, 4096, 0 );
  84.     }
  85. }
  86.  
  87. void client_process( int signo ){
  88.     struct message *msg;
  89.     msgrcv( msg_id, msg, 4096, SERVER_MESSAGE_TYPE + pid, 0 );
  90.     char *opcode = strtok( msg->mtext, " \t\n" );
  91.     if( !strcmp( opcode, "WRITE" ) ){
  92.         mwrite( msg );
  93.     }
  94.     else if( !strcmp( opcode, "KICK" ) ){
  95.         kick(); /* A chat ban like in IRC */
  96.     }
  97.     else if( !strcmp( opcode, "UPDATE_PTR" ) ){
  98.         update_ptr( msg );
  99.     }
  100.     else if( !strcmp( opcode, "READ" ) ){
  101.         mread();
  102.     }
  103. }
  104.  
  105. void mwrite( struct message *msg ){
  106.     strtok( msg->mtext, " \t\n" );
  107.     printf( "%s", strtok( NULL, "\n" ) );
  108.     fflush( stdout );
  109. }
  110.  
  111. void kick(){
  112.     printf( "You have been kicked from the chat server.\n" );
  113.     shmdt( shm_addr );
  114.     exit( 0 );
  115. }
  116.  
  117. void update_ptr( struct message *msg ){
  118.     strtok( msg->mtext, " \t" );
  119.     cur_addr = shm_addr + atoi( strtok( NULL, "\n" ) );
  120. }
  121.  
  122. void mread(){
  123.     /* This is just a driver function for now.
  124.      * Later I will modify it for a curses-like
  125.      * interface. */
  126.     char *str = memread();
  127.     printf( "%s\n", str );
  128. }
  129.  
  130. char *memread(){
  131.     char str[4096];
  132.     int i = 0;
  133.     int r = cur_addr - shm_addr;
  134.     while( likely( r + i < SHM_SIZE ) && cur_addr[i] != '\n' ){
  135.         str[i] = cur_addr[i++];
  136.     }
  137.     if( unlikely( r + i >= SHM_SIZE ) ){
  138.         strncpy( str+i, shm_addr, 4096-i );
  139.     }
  140.     return str;
  141. }
  142.  
  143. void register_shared_memory(){
  144.     key_t key = ftok( "/dev/zero", 64 );
  145.     shm_id = shmget( key, 65536 /* 64KB */, 0 );
  146.     shm_addr = shmat( shm_id, 0, SHM_RDONLY );
  147.     cur_addr = shm_addr;
  148. }
  149.  
  150. void register_message_queue(){
  151.     key_t key = ftok( "/dev/zero", 65 );
  152.     msg_id = msgget( key, 0 );
  153. }
  154.  
  155. void enter_raw_mode(){
  156.     tcgetattr( 0, &term );
  157.     save = term;
  158.     term.c_lflag &= ~ICANON;
  159.     tcsetattr( 0, TCSANOW, &term );
  160. }
  161.  
  162. void exit_raw_mode(){
  163.     tcsetattr( 0, TCSANOW, &save );
  164. }
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement