/**************************************************************************** * _______ _ ______ _______ _______ ______ * * ( ____ \( \ ( __ \ |\ /|( ___ )( )|\ /|( __ \ * * | ( \/| ( | ( \ )| ) ( || ( ) || () () || ) ( || ( \ ) * * | (__ | | | | ) || (___) || (___) || || || || | | || | ) | * * | __) | | | | | || ___ || ___ || |(_)| || | | || | | | * * | ( | | | | ) || ( ) || ( ) || | | || | | || | ) | * * | (____/\| (____/\| (__/ )| ) ( || ) ( || ) ( || (___) || (__/ ) * * (_______/(_______/(______/ |/ \||/ \||/ \|(_______)(______/ * * +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ * * |T|h|e| |O|a|k|l|a|n|d| |C|h|r|o|n|i|c|l|e|s| * * +-+-+-+ +-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+ * * ------------------------------------------------------------------------- * * EldhaMUD code (C) 2003-2005 by Robert Powell (Tommi) * * EldhaMUD Team: Celest, Altere and Krelowyn * * ------------------------------------------------------------------------- * * * ****************************************************************************/ /****************************************************** Desolation of the Dragon MUD II (C) 2000-2003 Jesse DeFer http://www.dotd.com dotd@dotd.com ******************************************************/ #include <stdio.h> #include <time.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #include <string.h> #include "./Headers/mud.h" /* License: * 1. This software comes with no warranty. * 2. This software is free, and may not be bought or sold. * 3. This software may be redistributed in source-only form, with this * license intact. * 4. This software may be redistributed with other software, only when * all of the following are met: * 1) the other software is in source form, * 2) the other software is free, * 3) this license does not conflict with the other software's license * 5. The comment below with the author's name must remain intact. */ /* MUD-MUD Communication via SysV IPC Message Queues * Allows multiple muds on the same box to share their immtalk channel * (and possibly other channels) * Author: Jesse DeFer dotd@dotd.com * AKA: Garil, Desolation of the Dragon II MUD - dotd.com 4000 * Version: 1.03 * Date: 12-2-2003 11:40MST */ /* Notes: * The message queue is set with world read/write permissions, * change this if you care. * * Should be very easy to port to any merc derivative, and fairly * easy to port to anything else. It was written and tested on * a SMAUG with modified channel code, however it should work on * any SMAUG without having to modify anything but a few defines. * Other muds will probably require rewriting recv_text_handler. * If you re-write recv_text_handler, send it and the defines you * modified to dotd@dotd.com and I'll include it in the next release. */ /* * Installation: * * 1. Customize this file, including the defines below and * * recv_text_handler (should be obvious what needs customizing) * * 2. Add a snippet like the following to your mud's channel code: * * if ( channel == CHANNEL_IMMTALK ) * * mud_message(ch, channel, argument); * * 3. Add a snippet like the following to your mud's event loop code: * * mud_recv_message(); */ /* customize these defines */ /* this should point to a file, a good file is something that doesn't change * very often, but is owned by you and unique, /vmlinuz is NOT a good file */ #define IPC_KEY_FILE "/vmlinuz" /* the port this mud runs on */ #define my_ipc_id 4600 /* the ports the other muds run on, you can include this port too if you want * and the code will skip it automatically, terminate with -1 */ const int other_ports[] = { 4600, 4700, -1 }; /* must include two %s's the first is the name, second is what they say * color codes and whatnot can be added */ #define IMMTALK_FORMAT "&B::&W%s&B:: '%s&B'\n\r" /* end customize these defines */ /* These should be customized if your mud doesn't have them */ #ifndef MAX_STRING_LENGTH #define MAX_STRING_LENGTH 4096 #endif #ifndef MAX_INPUT_LENGTH #define MAX_INPUT_LENGTH 1024 #endif #ifndef GET_NAME #define GET_NAME(ch) (ch)->name #endif #ifndef MAX_LEVEL #define MAX_LEVEL 1 #endif #define MAX_MSGBUF_LENGTH 2048 key_t keyval; int qid = -2; struct mud_msgbuf { long mtype; char mtext[MAX_MSGBUF_LENGTH + 1]; }; void close_queue( ) { msgctl( qid, IPC_RMID, 0 ); bug( "close_queue" ); } int open_queue( ) { struct msqid_ds qstat; int oldqid = qid; qstat.msg_qnum = 0; if( qid == -2 ) keyval = ftok( IPC_KEY_FILE, 'm' ); if( msgctl( qid, IPC_STAT, &qstat ) != -1 ) { if( qstat.msg_qnum > 50 ) close_queue( ); } if( ( qid = msgget( keyval, IPC_CREAT | 0666 ) ) == -1 ) { bug( "Unable to msgget keyval %d.", ( int )keyval ); return -1; } if( oldqid != qid ) { sprintf( log_buf, "msgget successful, qid: %d, keyval: %d", qid, ( int )keyval ); log_string( log_buf ); oldqid = qid; } return 1; } void mud_send_message( char *arg ) { struct mud_msgbuf qbuf; int x; if( open_queue( ) < 0 ) return; snprintf( qbuf.mtext, MAX_MSGBUF_LENGTH, "%s", arg ); for( x = 0; other_ports[x] != -1; x++ ) { if( other_ports[x] == my_ipc_id ) continue; qbuf.mtype = other_ports[x]; if( msgsnd( qid, &qbuf, strlen( qbuf.mtext ) + 1, 0 ) == -1 ) bug( "mud_send_message: errno: %d", errno ); } } void mud_message( CHAR_DATA * ch, int channel, char *arg ) { char tbuf[MAX_MSGBUF_LENGTH + 1]; int invis; invis = IS_NPC( ch ) ? ch->mobinvis : ch->pcdata->wizinvis; snprintf( tbuf, MAX_MSGBUF_LENGTH, "%d %d %d \"%s@%d\" %s", channel, invis, MAX_LEVEL, GET_NAME( ch ), my_ipc_id, arg ); mud_send_message( tbuf ); } void recv_text_handler( char *str ) { DESCRIPTOR_DATA *d; char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH], arg3[MAX_INPUT_LENGTH]; char chname[MAX_INPUT_LENGTH]; char buf[MAX_STRING_LENGTH - 1]; int channel = -1, ilevel = -1, maxlevel = -1; str = one_argument( str, arg1 ); str = one_argument( str, arg2 ); str = one_argument( str, arg3 ); str = one_argument( str, chname ); channel = atoi( arg1 ); ilevel = atoi( arg2 ); maxlevel = atoi( arg3 ); if( maxlevel < MAX_LEVEL ) ilevel += ( MAX_LEVEL - maxlevel ); else ilevel -= ( MAX_LEVEL - maxlevel ); if( ilevel < 0 ) ilevel = 1; snprintf( buf, MAX_STRING_LENGTH, IMMTALK_FORMAT, capitalize( chname ), str ); for( d = first_descriptor; d; d = d->next ) { CHAR_DATA *och; och = d->original ? d->original : d->character; if( !och || d->connected != CON_PLAYING || IS_SET( och->deaf, channel ) || get_trust( och ) < ilevel ) continue; /* * if ( get_trust( och ) < sysdata.think_level ) * if ( channel == CHANNEL_IMMTALK ) * continue; */ set_char_color( AT_LOG, och ); send_to_char( buf, och ); } } void mud_recv_message( ) { struct mud_msgbuf qbuf; int ret; if( open_queue( ) < 0 ) return; while( ( ret = msgrcv( qid, &qbuf, MAX_MSGBUF_LENGTH, my_ipc_id, IPC_NOWAIT ) ) > 0 ) recv_text_handler( qbuf.mtext ); if( ret == -1 && errno != ENOMSG ) bug( "mud_recv_message: errno: %d", errno ); }