/* * EPIC, PCI, and I/O devices. * Initialize Mousse Platform, probe for PCI devices, * Query configuration parameters if not set. */ int misc_init_f (void) { #if 0 m48_tod_init(); /* Init SGS M48T59Y TOD/NVRAM */ printf("RTC: M48T589 TOD/NVRAM (%d) bytes\n", TOD_NVRAM_SIZE); get_tod(); #endif sys_led_msg("BOOT"); return 0; }
void num_file_start(num_state * state, tw_bf * bf, unsigned int size, tw_lp * lp) { #if NUM_VERIFY if(lp->id == DEBUG_LP) printf("%ld T%d %s: FILE_START size: %.2lfB\n", lp->id, state->type, get_tod(tw_now(lp)), (double) size / 8.0); #endif // send event down to TCP state->file_size = size; state->stats->s_nstart++; state->start = tw_now(lp); rn_event_send(rn_event_new(lp, 0.0, lp, DOWNSTREAM, size/8)); }
void num_file_stop(num_state * state, tw_bf * bf, tw_lp * lp) { #if NUM_VERIFY if(lp->id == DEBUG_LP) printf("%ld T%d %s: FILE_STOP\n", lp->id, state->type, get_tod(tw_now(lp))); #endif state->stats->s_nstop++; if(g_num_mod < 1) return; // send event down to TCP rn_event_send(rn_event_new(lp, 0.0, lp, DOWNSTREAM, 0)); }
/** * Main apply handler. * * Checks for unpaid items before applying. * @param op ::object causing tmp to be applied. * @param tmp ::object being applied. * @param aflag Special (always apply/unapply) flags. Nothing is done * with them in this function - they are passed to apply_special(). * @retval 0 Player or monster can't apply objects of that type. * @retval 1 Has been applied, or there was an error applying the object. * @retval 2 Objects of that type can't be applied if not in * inventory. */ int manual_apply(object *op, object *tmp, int aflag) { if (tmp->head) { tmp = tmp->head; } if (op->type == PLAYER) { CONTR(op)->praying = 0; } if (QUERY_FLAG(tmp, FLAG_UNPAID) && !QUERY_FLAG(tmp, FLAG_APPLIED)) { if (op->type == PLAYER) { new_draw_info(NDI_UNIQUE, op, "You should pay for it first."); return 1; } /* Monsters just skip unpaid items */ else { return 0; } } /* Monsters must not apply random chests, nor magic_mouths with a counter */ if (op->type != PLAYER && tmp->type == TREASURE) { return 0; } /* Trigger the APPLY event */ if (!(aflag & AP_NO_EVENT) && trigger_event(EVENT_APPLY, op, tmp, NULL, NULL, aflag, 0, 0, SCRIPT_FIX_ACTIVATOR)) { return 1; } aflag &= ~AP_NO_EVENT; /* Control apply by controling a set exp object level or player exp level */ if (tmp->item_level) { int tmp_lev; if (tmp->item_skill) { tmp_lev = find_skill_exp_level(op, tmp->item_skill); } else { tmp_lev = op->level; } if (tmp->item_level > tmp_lev) { new_draw_info(NDI_UNIQUE, op, "The item level is too high to apply."); return 1; } } switch (tmp->type) { case HOLY_ALTAR: new_draw_info_format(NDI_UNIQUE, op, "You touch the %s.", tmp->name); if (change_skill(op, SK_PRAYING)) { pray_at_altar(op, tmp); } else { new_draw_info(NDI_UNIQUE, op, "Nothing happens. It seems you miss the right skill."); } return 1; break; case HANDLE: new_draw_info(NDI_UNIQUE, op, "You turn the handle."); play_sound_map(op->map, op->x, op->y, SOUND_TURN_HANDLE, SOUND_NORMAL); tmp->value = tmp->value ? 0 : 1; SET_ANIMATION(tmp, ((NUM_ANIMATIONS(tmp) / NUM_FACINGS(tmp)) * tmp->direction) + tmp->value); update_object(tmp, UP_OBJ_FACE); push_button(tmp); return 1; case TRIGGER: if (check_trigger(tmp, op)) { new_draw_info(NDI_UNIQUE, op, "You turn the handle."); play_sound_map(tmp->map, tmp->x, tmp->y, SOUND_TURN_HANDLE, SOUND_NORMAL); } else { new_draw_info(NDI_UNIQUE, op, "The handle doesn't move."); } return 1; case EXIT: if (op->type != PLAYER || !tmp->map) { return 0; } /* If no map path specified, we assume it is the map path of the exit. */ if (!EXIT_PATH(tmp)) { FREE_AND_ADD_REF_HASH(EXIT_PATH(tmp), tmp->map->path); } if (!EXIT_PATH(tmp) || !is_legal_2ways_exit(op, tmp) || (EXIT_Y(tmp) == -1 && EXIT_X(tmp) == -1)) { new_draw_info_format(NDI_UNIQUE, op, "The %s is closed.", query_name(tmp, NULL)); } else { /* Don't display messages for random maps. */ if (tmp->msg && strncmp(EXIT_PATH(tmp), "/!", 2) && strncmp(EXIT_PATH(tmp), "/random/", 8)) { new_draw_info(NDI_NAVY, op, tmp->msg); } enter_exit(op, tmp); } return 1; case SIGN: apply_sign(op, tmp); return 1; case BOOK: if (op->type == PLAYER) { apply_book(op, tmp); return 1; } return 0; case SKILLSCROLL: if (op->type == PLAYER) { apply_skillscroll(op, tmp); return 1; } return 0; case SPELLBOOK: if (op->type == PLAYER) { apply_spellbook(op, tmp); return 1; } return 0; case SCROLL: apply_scroll(op, tmp); return 1; case POTION: (void) apply_potion(op, tmp); return 1; case LIGHT_APPLY: apply_player_light(op, tmp); return 1; case LIGHT_REFILL: apply_player_light_refill(op, tmp); return 1; /* Eneq(@csd.uu.se): Handle apply on containers. */ case CLOSE_CON: if (op->type == PLAYER) { (void) esrv_apply_container(op, tmp->env); } return 1; case CONTAINER: if (op->type == PLAYER) { (void) esrv_apply_container(op, tmp); } return 1; case TREASURE: apply_treasure(op, tmp); return 1; case WEAPON: case ARMOUR: case BOOTS: case GLOVES: case AMULET: case GIRDLE: case BRACERS: case SHIELD: case HELMET: case RING: case CLOAK: case WAND: case ROD: case HORN: case SKILL: case BOW: case SKILL_ITEM: /* Not in inventory */ if (tmp->env != op) { return 2; } (void) apply_special(op, tmp, aflag); return 1; case DRINK: case FOOD: case FLESH: apply_food(op, tmp); return 1; case POISON: apply_poison(op, tmp); return 1; case SAVEBED: if (op->type == PLAYER) { apply_savebed(op); return 1; } return 0; case ARMOUR_IMPROVER: if (op->type == PLAYER) { apply_armour_improver(op, tmp); return 1; } return 0; case WEAPON_IMPROVER: apply_weapon_improver(op, tmp); return 1; case CLOCK: if (op->type == PLAYER) { timeofday_t tod; get_tod(&tod); new_draw_info_format(NDI_UNIQUE, op, "It is %d minute%s past %d o'clock %s", tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"), ((tod.hour % (HOURS_PER_DAY / 2) == 0) ? (HOURS_PER_DAY / 2) : ((tod.hour) % (HOURS_PER_DAY / 2))), ((tod.hour >= (HOURS_PER_DAY / 2)) ? "pm" : "am")); return 1; } return 0; case POWER_CRYSTAL: apply_power_crystal(op, tmp); return 1; /* For lighting torches/lanterns/etc */ case LIGHTER: if (op->type == PLAYER) { apply_lighter(op, tmp); return 1; } return 0; /* So the below default case doesn't execute for these objects, * even if they have message. */ case DOOR: return 0; /* Nothing from the above... but show a message if it has one. */ default: if (tmp->msg) { new_draw_info(NDI_UNIQUE, op, tmp->msg); return 1; } return 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( ¤t_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; }
/* * num_file_complete: handler routine for file completions * * Files may complete in two ways: * * 1. TCP sends an UPSTREAM event with file x-fer size * 2. TCP sends an UPSTREAM event with file size 0 * (indicates TCP failure) * * Upon completion, if throughput is good, ask for a larger file. * If throughput is less than desired, but acceptable, ask for * same size file. If throughput is not acceptable, ask for * minimum size file. */ void num_file_complete(num_state * state, tw_bf * bf, rn_message * msg, tw_lp * lp) { tw_stime elapsed; tw_stime ts, tn; num_profile *np; int actual; int timeofday; #if NUM_VERIFY if(lp->id == DEBUG_LP) printf("%ld T%d %s: FILE_COMPLETE\n", lp->id, state->type, get_tod(tw_now(lp))); #endif tn = tw_now(lp); timeofday = (int) tn % TWENTY_FOUR_HOURS; elapsed = tn - state->start; if(msg->size == 40) { tw_error(TW_LOC, "Received TCP ACK!"); } else if (msg->size > 40) { state->stats->s_total_time += elapsed; state->stats->s_total_kb += state->file_size; state->stats->s_nfiles++; } else { // try again? state->stats->s_nfailures = 3;; return; } actual = state->file_size / elapsed; np = &g_num_profiles[state->type]; #if NUM_VERIFY if(lp->id == DEBUG_LP) { printf("%ld T%d %s: actual: %d, desired: %u, size: %.2lfB, elapsed: %lf\n", lp->id, state->type, get_tod(tw_now(lp)), actual, np->bitrate, (double) state->file_size / 8.0, elapsed); } #endif #if ONE if(lp->id != DEBUG_LP) return; #endif // If after quitting time, then do not ask for another file if(timeofday >= QUIT_TIME) return; // Both rate and desired are in bits / second if(actual >= np->bitrate) { // Stay with file_size if achieved the desired bitrate ts = tn + ((state->file_size / np->bitrate) - elapsed); if ( ts <= tn ) ts = tn + 1.0; if((int) ts % TWENTY_FOUR_HOURS >= QUIT_TIME) return; rn_timer_init(lp, ts); } else if (actual >= np->bitrate / 10.0) { // Ask for another file right away state->file_size *= 2; if(state->file_size > MAX_FILE_SIZE) state->file_size = MAX_FILE_SIZE; num_file_start(state, bf, state->file_size, lp); } else { // rate is less than acceptable, walk away from network // this would be stage 2 state->stats->s_nfailures = 2; } }