Exemplo n.º 1
0
    void CHSInterface::BroadcastWithFlags(HS_INT32 iFlags,
                                          HS_INT32 iToggles,
                                          const HS_INT8 * pcFormat, ...)
#endif
{
    va_list args;

    static char buff[HSPACE_MAX_HSPRINTF_LEN];

    va_start(args, pcFormat);
    vsnprintf(buff, HSPACE_MAX_HSPRINTF_LEN, pcFormat, args);

    buff[HSPACE_MAX_HSPRINTF_LEN - 1] = '\0';
    va_end(args);


#ifdef PENNMUSH
    flag_broadcast(iFlags, iToggles, buff);
#endif
#if defined(TM3) || defined(MUX)
    raw_broadcast(iToggles, buff);
#endif
}
Exemplo n.º 2
0
void boot_slave( void ) {
    int sv[2];

    int i;

    int maxfds;

    char *s;

#ifdef HAVE_GETDTABLESIZE
    maxfds = getdtablesize();
#else
    maxfds = sysconf( _SC_OPEN_MAX );
#endif

    if( slave_socket != -1 ) {
        close( slave_socket );
        slave_socket = -1;
    }
    if( socketpair( AF_UNIX, SOCK_DGRAM, 0, sv ) < 0 ) {
        return;
    }
    /*
     * set to nonblocking
     */
#ifdef FNDELAY
    if( fcntl( sv[0], F_SETFL, FNDELAY ) == -1 ) {
#else
    if( fcntl( sv[0], F_SETFL, O_NDELAY ) == -1 ) {
#endif
        close( sv[0] );
        close( sv[1] );
        return;
    }
    slave_pid = vfork();
    switch( slave_pid ) {
    case -1:
        close( sv[0] );
        close( sv[1] );
        return;

    case 0:		/* child */
        close( sv[0] );
        if( dup2( sv[1], 0 ) == -1 ) {
            _exit( 1 );
        }
        if( dup2( sv[1], 1 ) == -1 ) {
            _exit( 1 );
        }
        for( i = 3; i < maxfds; ++i ) {
            close( i );
        }
        s = ( char * ) XMALLOC( MBUF_SIZE, "boot_slave" );
        sprintf( s, "%s/slave", mudconf.binhome );
        execlp( s, "slave", NULL );
        XFREE( s, "boot_slave" );
        _exit( 1 );
    }
    close( sv[1] );

#ifdef FNDELAY
    if( fcntl( sv[0], F_SETFL, FNDELAY ) == -1 ) {
#else
    if( fcntl( sv[0], F_SETFL, O_NDELAY ) == -1 ) {
#endif
        close( sv[0] );
        return;
    }
    slave_socket = sv[0];
    log_write( LOG_ALWAYS, "NET", "SLAVE", "DNS lookup slave started on fd %d", slave_socket );
}

int make_socket( int port ) {
    int s, opt;

    struct sockaddr_in server;

    s = socket( AF_INET, SOCK_STREAM, 0 );
    if( s < 0 ) {
        log_perror( "NET", "FAIL", NULL, "creating master socket" );
        exit( 3 );
    }
    opt = 1;
    if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR,
                    ( char * ) &opt, sizeof( opt ) ) < 0 ) {
        log_perror( "NET", "FAIL", NULL, "setsockopt" );
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = ( unsigned short ) htons( ( unsigned short ) port );
    if( !mudstate.restarting )
        if( bind( s, ( struct sockaddr * ) &server, sizeof( server ) ) ) {
            log_perror( "NET", "FAIL", NULL, "bind" );
            close( s );
            exit( 4 );
        }
    listen( s, 5 );
    return s;
}

void shovechars( int port ) {
    fd_set input_set, output_set;

    struct timeval last_slice, current_time, next_slice, timeout,
            slice_timeout;
    int found, check;

    DESC *d, *dnext, *newd;

    int avail_descriptors, maxfds;

    struct stat fstatbuf;

#define CheckInput(x)	FD_ISSET(x, &input_set)
#define CheckOutput(x)	FD_ISSET(x, &output_set)

    mudstate.debug_cmd = ( char * ) "< shovechars >";
    if( !mudstate.restarting ) {
        sock = make_socket( port );
    }
    if( !mudstate.restarting ) {
        maxd = sock + 1;
    }

    get_tod( &last_slice );

#ifdef HAVE_GETDTABLESIZE
    maxfds = getdtablesize();
#else
    maxfds = sysconf( _SC_OPEN_MAX );
#endif

    avail_descriptors = maxfds - 7;

    while( mudstate.shutdown_flag == 0 ) {
        get_tod( &current_time );
        last_slice = update_quotas( last_slice, current_time );

        process_commands();

        if( mudstate.shutdown_flag ) {
            break;
        }

        /*
         * We've gotten a signal to dump flatfiles
         */

        if( mudstate.flatfile_flag && !mudstate.dumping ) {
            if( *mudconf.dump_msg ) {
                raw_broadcast( 0, "%s", mudconf.dump_msg );
            }

            mudstate.dumping = 1;
            log_write( LOG_DBSAVES, "DMP", "CHKPT", "Flatfiling: %s.#%d#", mudconf.db_file, mudstate.epoch );
            dump_database_internal( DUMP_DB_FLATFILE );
            mudstate.dumping = 0;

            if( *mudconf.postdump_msg ) {
                raw_broadcast( 0, "%s", mudconf.postdump_msg );
            }
            mudstate.flatfile_flag = 0;
        }
        /*
         * test for events
         */

        dispatch();

        /*
         * any queued robot commands waiting?
         */

        timeout.tv_sec = que_next();
        timeout.tv_usec = 0;
        next_slice = msec_add( last_slice, mudconf.timeslice );
        slice_timeout = timeval_sub( next_slice, current_time );

        FD_ZERO( &input_set );
        FD_ZERO( &output_set );

        /*
         * Listen for new connections if there are free descriptors
         */

        if( ndescriptors < avail_descriptors ) {
            FD_SET( sock, &input_set );
        }
        /*
         * Listen for replies from the slave socket
         */

        if( slave_socket != -1 ) {
            FD_SET( slave_socket, &input_set );
        }
        /*
         * Mark sockets that we want to test for change in status
         */

        DESC_ITER_ALL( d ) {
            if( !d->input_head ) {
                FD_SET( d->descriptor, &input_set );
            }
            if( d->output_head ) {
                FD_SET( d->descriptor, &output_set );
            }
        }

        /*
         * Wait for something to happen
         */
        found = select( maxd, &input_set, &output_set, ( fd_set * ) NULL,
                        &timeout );

        if( found < 0 ) {
            if( errno == EBADF ) {
                /*
                 * This one is bad, as it results in a spiral
                 * of doom, unless we can figure out what the
                 * bad file descriptor is and get rid of it.
                 */
                log_perror( "NET", "FAIL", "checking for activity", "select" );
                DESC_ITER_ALL( d ) {
                    if( fstat( d->descriptor,
                               &fstatbuf ) < 0 ) {
                        /*
                         * It's a player. Just toss
                         * the connection.
                         */
                        log_write( LOG_PROBLEMS, "ERR", "EBADF", "Bad descriptor %d", d->descriptor );
                        shutdownsock( d,R_SOCKDIED );
                    }
                }
                if( ( slave_socket == -1 ) ||
                        ( fstat( slave_socket, &fstatbuf ) < 0 ) ) {
                    /*
                     * Try to restart the slave, since it
                     * presumably died.
                     */
                    log_write( LOG_PROBLEMS, "ERR", "EBADF", "Bad slave descriptor %d", slave_socket );
                    boot_slave();
                }
                if( ( sock != -1 ) &&
                        ( fstat( sock, &fstatbuf ) < 0 ) ) {
                    /*
                     * That's it, game over.
                     */
                    log_write( LOG_PROBLEMS, "ERR", "EBADF", "Bad game port descriptor %d", sock );
                    break;
                }
            } else if( errno != EINTR ) {
                log_perror( "NET", "FAIL", "checking for activity", "select" );
            }
            continue;
        }
Exemplo n.º 3
0
void do_kill (dbref player, dbref cause, int key, char *what, char *costchar)
{
dbref	victim;
char	*buf1, *buf2;
int	cost;

	init_match(player, what, TYPE_PLAYER);
	match_neighbor();
	match_me();
	match_here();
	if (Wizard(player)) {
		match_player();
		match_absolute();
	}
	victim = match_result();

	switch (victim) {
	case NOTHING:
		notify(player, "I don't see that player here.");
		break;
	case AMBIGUOUS:
		notify(player, "I don't know who you mean!");
		break;
	default:
		if ((Typeof(victim) != TYPE_PLAYER) &&
		    (Typeof(victim) != TYPE_THING)) {
			notify(player,
				"Sorry, you can only kill players and things.");
			break;
		}
		if ((Haven(Location(victim)) && !Wizard(player)) ||
		    (controls(victim, Location(victim)) &&
		     !controls(player, Location(victim))) ||
		    Immortal(victim)) {
			notify(player, "Sorry.");
			break;
		}
		if (key == KILL_SLAY) {
		  if (Builder(player) && Builder(victim)) {
			notify(player, "Sorry.");
			break;
		  }
		}

		/* go for it */

		cost = atoi(costchar);
		if (key == KILL_KILL) {
			if (HasPriv(victim,player,POWER_NOKILL,POWER4,NOTHING)) {
			  notify(player, "Sorry.");
			  break;
			}
			if (cost < mudconf.killmin)
				cost = mudconf.killmin;
			if (cost > mudconf.killmax)
				cost = mudconf.killmax;

			/* see if it works */

			if (!payfor(player, cost)) {
				notify(player,
					unsafe_tprintf("You don't have enough %s.",
						mudconf.many_coins));
				return;
			}
		} else {
			cost = 0;
		}

		if (!(((random() % mudconf.killguarantee) < cost) ||
		      (key == KILL_SLAY)) ||
		    Wizard(victim)) {

			/* Failure: notify player and victim only */

			notify(player, "Your murder attempt failed.");
			buf1 = alloc_lbuf("do_kill.failed");
			sprintf(buf1, "%s tried to kill you!", Name(player));
			notify_with_cause(victim, player, buf1);
			if (Suspect(player)) {
				strcpy(buf1, Name(player));
				if (player == Owner(player)) {
					raw_broadcast(0, WIZARD,
						"[Suspect] %s tried to kill %s(#%d).",
						buf1, Name(victim), victim);
				} else {
					buf2 = alloc_lbuf("do_kill.SUSP.failed");
					strcpy(buf2, Name(Owner(player)));
					raw_broadcast(0, WIZARD,
						"[Suspect] %s <via %s(#%d)> tried to kill %s(#%d).",
						buf2, buf1, player,
						Name(victim), victim);
					free_lbuf(buf2);
				}
			}
			free_lbuf(buf1);
			break;
		}

		/* Success!  You killed him */

		buf1 = alloc_lbuf("do_kill.succ.1");
		buf2 = alloc_lbuf("do_kill.succ.2");
		if (Suspect(player)) {
			strcpy(buf1, Name(player));
			if (player == Owner(player)) {
				raw_broadcast(0, WIZARD,
					"[Suspect] %s killed %s(#%d).",
					buf1, Name(victim), victim);
			} else {
				strcpy(buf2, Name(Owner(player)));
				raw_broadcast(0, WIZARD,
					"[Suspect] %s <via %s(#%d)> killed %s(#%d).",
					buf2, buf1, player, Name(victim),
					victim);
			}
		}
		sprintf(buf1, "You killed %s!", Name(victim));
		sprintf(buf2, "killed %s!", Name(victim));
		if (Typeof(victim) != TYPE_PLAYER)
			if (halt_que(NOTHING, victim) > 0)
				if (!Quiet(victim))
					notify(Owner(victim), "Halted.");
		did_it(player, victim, A_KILL, buf1, A_OKILL, buf2, A_AKILL,
			(char **)NULL, 0);

		/* notify victim */

		sprintf(buf1, "%s killed you!", Name(player));
		notify_with_cause(victim, player, buf1);

		/* Pay off the bonus */

		if (key == KILL_KILL) {
			cost /= 2; 	/* victim gets half */
			if (Pennies(Owner(victim)) < mudconf.paylimit) {
				sprintf(buf1,
					"Your insurance policy pays %d %s.",
					cost, mudconf.many_coins);
				notify(victim, buf1);
				giveto(Owner(victim), cost, NOTHING);
			} else {
				notify(victim,
					"Your insurance policy has been revoked.");
			}
		}
		free_lbuf(buf1);
		free_lbuf(buf2);

		/* send him home */

		move_via_generic(victim, HOME, NOTHING, 0);
		divest_object(victim);
		break;
	}
}
Exemplo n.º 4
0
void do_dbclean( dbref player, dbref cause, int key ) {
    VATTR *vp, *vpx;

    dbref i, end;

    int ca, n_oldtotal, n_oldtop, n_deleted, n_renumbered, n_objt, n_atrt,
        got;
    char *as, *str;

    int *used_table;

    ATTR **new_table;

    UFUN *ufp;

    CMDENT *cmdp;

    ADDENT *addp;

    raw_broadcast( 0, "GAME: Cleaning database. Game may freeze for a few minutes." );

    used_table = ( int * ) XCALLOC( mudstate.attr_next, sizeof( int ),
                                    "dbclean.used_table" );

    n_oldtotal = mudstate.attr_next;
    n_oldtop = anum_alc_top;
    n_deleted = n_renumbered = n_objt = n_atrt = 0;

    /*
     * Non-user-defined attributes are always considered used.
     */

    for( i = 0; i < A_USER_START; i++ ) {
        used_table[i] = i;
    }

    /*
     * Walk the database. Mark all the attribute numbers in use.
     */

    atr_push();
    DO_WHOLE_DB( i ) {
        for( ca = atr_head( i, &as ); ca; ca = atr_next( &as ) ) {
            used_table[ca] = ca;
        }
    }
    atr_pop();

    /*
     * Walk the vattr table. If a number isn't in use, zorch it.
     */

    vp = vattr_first();
    while( vp ) {
        vpx = vp;
        vp = vattr_next( vp );
        if( used_table[vpx->number] == 0 ) {
            anum_set( vpx->number, NULL );
            hashdelete( vpx->name, &mudstate.vattr_name_htab );
            XFREE( vpx, "dbclean.vpx" );
            n_deleted++;
        }
    }

    /*
     * The user-defined function, added command, and hook structures embed
     * * attribute numbers. Clean out the ones we've deleted, resetting them
     * * to the *Invalid (A_TEMP) attr.
     */

    for( ufp = ( UFUN * ) hash_firstentry( &mudstate.ufunc_htab );
            ufp != NULL; ufp = ( UFUN * ) hash_nextentry( &mudstate.ufunc_htab ) ) {
        if( used_table[ufp->atr] == 0 ) {
            ufp->atr = A_TEMP;
        }
    }
    for( cmdp = ( CMDENT * ) hash_firstentry( &mudstate.command_htab );
            cmdp != NULL;
            cmdp = ( CMDENT * ) hash_nextentry( &mudstate.command_htab ) ) {
        if( cmdp->pre_hook ) {
            if( used_table[cmdp->pre_hook->atr] == 0 ) {
                cmdp->pre_hook->atr = A_TEMP;
            }
        }
        if( cmdp->post_hook ) {
            if( used_table[cmdp->post_hook->atr] == 0 ) {
                cmdp->post_hook->atr = A_TEMP;
            }
        }
        if( cmdp->userperms ) {
            if( used_table[cmdp->userperms->atr] == 0 ) {
                cmdp->userperms->atr = A_TEMP;
            }
        }
        if( cmdp->callseq & CS_ADDED ) {
            for( addp = ( ADDENT * ) cmdp->info.added;
                    addp != NULL; addp = addp->next ) {
                if( used_table[addp->atr] == 0 ) {
                    addp->atr = A_TEMP;
                }
            }
        }
    }

    /*
     * Walk the table we've created of used statuses. When we find free
     * * slots, walk backwards to the first used slot at the end of the
     * * table. Write the number of the free slot into that used slot.
     */

    for( i = A_USER_START, end = mudstate.attr_next - 1;
            ( i < mudstate.attr_next ) && ( i < end ); i++ ) {
        if( used_table[i] == 0 ) {
            while( ( end > i ) && ( used_table[end] == 0 ) ) {
                end--;
            }
            if( end > i ) {
                used_table[end] = used_table[i] = i;
                end--;
            }
        }
    }

    /*
     * Renumber the necessary attributes in the vattr tables.
     */

    for( i = A_USER_START; i < mudstate.attr_next; i++ ) {
        if( used_table[i] != i ) {
            vp = ( VATTR * ) anum_get( i );
            if( vp ) {
                vp->number = used_table[i];
                vp->flags |= AF_DIRTY;
                anum_set( used_table[i], ( ATTR * ) vp );
                anum_set( i, NULL );
                n_renumbered++;
            }
        }
    }

    /*
     * Now we walk the database. For every object, if we have an attribute
     * * we're renumbering (the slot number is not equal to the array value
     * * at that slot), we delete the old attribute and add the new one.
     */

    atr_push();
    DO_WHOLE_DB( i ) {
        got = 0;
        for( ca = atr_head( i, &as ); ca; ca = atr_next( &as ) ) {
            if( used_table[ca] != ca ) {
                str = atr_get_raw( i, ca );
                atr_add_raw( i, used_table[ca], str );
                atr_clr( i, ca );
                n_atrt++;
                got = 1;
            }
        }
        if( got ) {
            n_objt++;
        }
    }
    atr_pop();

    /*
     * The new end of the attribute table is the first thing we've
     * * renumbered.
     */

    for( end = A_USER_START;
            ( ( end == used_table[end] ) && ( end < mudstate.attr_next ) ); end++ );
    mudstate.attr_next = end;

    /*
     * We might be able to shrink the size of the attribute table.
     * * If the current size of the table is less than the initial
     * * size, shrink it back down to the initial size.
     * * Otherwise, shrink it down so it's the current top plus the
     * * initial size, as if we'd just called anum_extend() for it.
     */

    if( anum_alc_top > mudconf.init_size + A_USER_START ) {
        if( mudstate.attr_next < mudconf.init_size + A_USER_START ) {
            end = mudconf.init_size + A_USER_START;
        } else {
            end = mudstate.attr_next + mudconf.init_size;
        }
        if( end < anum_alc_top ) {
            new_table = ( ATTR ** ) XCALLOC( end + 1, sizeof( ATTR * ),
                                             "dbclean.new_table" );
            for( i = 0; i < mudstate.attr_next; i++ ) {
                new_table[i] = anum_table[i];
            }
            XFREE( anum_table, "dbclean.anum_table" );
            anum_table = new_table;
            anum_alc_top = end;
        }
    }

    /*
     * Go through the function and added command tables again, and
     * * take care of the attributes that got renumbered.
     */

    for( ufp = ( UFUN * ) hash_firstentry( &mudstate.ufunc_htab );
            ufp != NULL; ufp = ( UFUN * ) hash_nextentry( &mudstate.ufunc_htab ) ) {
        if( used_table[ufp->atr] != ufp->atr ) {
            ufp->atr = used_table[ufp->atr];
        }
    }
    for( cmdp = ( CMDENT * ) hash_firstentry( &mudstate.command_htab );
            cmdp != NULL;
            cmdp = ( CMDENT * ) hash_nextentry( &mudstate.command_htab ) ) {
        if( cmdp->pre_hook ) {
            if( used_table[cmdp->pre_hook->atr] !=
                    cmdp->pre_hook->atr )
                cmdp->pre_hook->atr =
                    used_table[cmdp->pre_hook->atr];
        }
        if( cmdp->post_hook ) {
            if( used_table[cmdp->post_hook->atr] !=
                    cmdp->post_hook->atr )
                cmdp->post_hook->atr =
                    used_table[cmdp->post_hook->atr];
        }
        if( cmdp->userperms ) {
            if( used_table[cmdp->userperms->atr] !=
                    cmdp->userperms->atr )
                cmdp->userperms->atr =
                    used_table[cmdp->userperms->atr];
        }
        if( cmdp->callseq & CS_ADDED ) {
            for( addp = ( ADDENT * ) cmdp->info.added;
                    addp != NULL; addp = addp->next ) {
                if( used_table[addp->atr] != addp->atr ) {
                    addp->atr = used_table[addp->atr];
                }
            }
        }
    }

    /*
     * Clean up.
     */

    XFREE( used_table, "dbclean.used_table" );

    if( anum_alc_top != n_oldtop ) {
        notify_check( player, player, MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN, "Cleaned %d user attribute slots (reduced to %d): %d deleted, %d renumbered (%d objects and %d individual attrs touched). Table size reduced from %d to %d.", n_oldtotal - A_USER_START, mudstate.attr_next - A_USER_START, n_deleted, n_renumbered, n_objt, n_atrt, n_oldtop, anum_alc_top );
    } else {
        notify_check( player, player, MSG_PUP_ALWAYS|MSG_ME_ALL|MSG_F_DOWN, "Cleaned %d attributes (now %d): %d deleted, %d renumbered (%d objects and %d individual attrs touched).", n_oldtotal, mudstate.attr_next, n_deleted, n_renumbered, n_objt, n_atrt );
        
    }

    raw_broadcast( 0, "GAME: Database cleaning complete." );

}