Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #include <stdlib.h>
- #include <sys/ipc.h>
- #include <sys/shm.h>
- #include <sys/msg.h>
- #include <termios.h>
- #include <signal.h>
- #include <proc/procps.h>
- #include "chat.h"
- char nick[10];
- pid_t pid;
- struct termios term;
- struct termios save;
- int main( int argc, char **argv ){
- signals();
- register_shared_memory();
- register_message_queue();
- enter_raw_mode();
- setup_user();
- input_loop();
- exit_raw_mode();
- return 0;
- }
- void signals(){
- signal( SIGTSTP, stop );
- signal( SIGINT, quit );
- signal( SIGTERM, quit );
- signal( SIGCONT, cont );
- signal( SIGPOLL, client_process );
- }
- void stop( int signo ){
- tcsetattr( 0, TCSANOW, &save );
- raise( SIGSTOP );
- }
- void cont( int signo ){
- tcsetattr( 0, TCSANOW, &term );
- }
- void quit( int signo ){
- tcsetattr( 0, TCSANOW, &save );
- exit( 0 );
- }
- void setup_user( void ){
- pid = getpid();
- struct message *msg;
- msg->mtype = pid;
- msg->mtext = "JOIN\n";
- msgsnd( msg_id, msg, 4096, 0 );
- msgrcv( msg_id, msg, 4096, SERVER_MESSAGE_TYPE + pid, 0 );
- mwrite( msg );
- tcsetattr( 0, TCSANOW, &save );
- fgets( nick, 10, stdin );
- /* Will fgets() work in raw mode? */
- tcsetattr( 0, TCSAFLUSH, &term );
- msg->mtext = nick;
- msgsnd( msg_id, msg, 4096, 0 );
- msgrcv( msg_id, msg, 4096, SERVER_MESSAGE_TYPE + pid, 0 );
- mwrite( msg );
- }
- void input_loop(){
- struct message *msg;
- msg->mtype = pid;
- char buf[4092]; /* Size is 4 bytes less to prevent buffer overflows. */
- for(;;){
- fgets( buf, 4092, stdin );
- if( !strncmp( buf, "bye\n", 4 ) ){
- msg->mtext = "BYE\n";
- }
- else{
- sprintf( msg->mtext, "SAY %s", buf );
- }
- msgsnd( msg_id, msg, 4096, 0 );
- }
- }
- void client_process( int signo ){
- struct message *msg;
- msgrcv( msg_id, msg, 4096, SERVER_MESSAGE_TYPE + pid, 0 );
- char *opcode = strtok( msg->mtext, " \t\n" );
- if( !strcmp( opcode, "WRITE" ) ){
- mwrite( msg );
- }
- else if( !strcmp( opcode, "KICK" ) ){
- kick(); /* A chat ban like in IRC */
- }
- else if( !strcmp( opcode, "UPDATE_PTR" ) ){
- update_ptr( msg );
- }
- else if( !strcmp( opcode, "READ" ) ){
- mread();
- }
- }
- void mwrite( struct message *msg ){
- strtok( msg->mtext, " \t\n" );
- printf( "%s", strtok( NULL, "\n" ) );
- fflush( stdout );
- }
- void kick(){
- printf( "You have been kicked from the chat server.\n" );
- shmdt( shm_addr );
- exit( 0 );
- }
- void update_ptr( struct message *msg ){
- strtok( msg->mtext, " \t" );
- cur_addr = shm_addr + atoi( strtok( NULL, "\n" ) );
- }
- void mread(){
- /* This is just a driver function for now.
- * Later I will modify it for a curses-like
- * interface. */
- char *str = memread();
- printf( "%s\n", str );
- }
- char *memread(){
- char str[4096];
- int i = 0;
- int r = cur_addr - shm_addr;
- while( likely( r + i < SHM_SIZE ) && cur_addr[i] != '\n' ){
- str[i] = cur_addr[i++];
- }
- if( unlikely( r + i >= SHM_SIZE ) ){
- strncpy( str+i, shm_addr, 4096-i );
- }
- return str;
- }
- void register_shared_memory(){
- key_t key = ftok( "/dev/zero", 64 );
- shm_id = shmget( key, 65536 /* 64KB */, 0 );
- shm_addr = shmat( shm_id, 0, SHM_RDONLY );
- cur_addr = shm_addr;
- }
- void register_message_queue(){
- key_t key = ftok( "/dev/zero", 65 );
- msg_id = msgget( key, 0 );
- }
- void enter_raw_mode(){
- tcgetattr( 0, &term );
- save = term;
- term.c_lflag &= ~ICANON;
- tcsetattr( 0, TCSANOW, &term );
- }
- void exit_raw_mode(){
- tcsetattr( 0, TCSANOW, &save );
- }
Advertisement
Advertisement
Advertisement
RAW Paste Data
Copied
Advertisement