void log_with_timestamp(io::WriteFile& out, XString line) { if (!line) { out.put('\n'); return; } timestamp_milliseconds_buffer tmpstr; stamp_time(tmpstr); out.really_put(tmpstr.data(), tmpstr.size()); out.really_put(": ", 2); out.put_line(line); }
int main(int argc, char *argv[]) { // These are all the signals we are likely to get // The shell handles stop/cont signal(SIGTERM, stop_process); signal(SIGINT, stop_process); signal(SIGQUIT, stop_process); signal(SIGABRT, stop_process); workdir = make_path(ZString(strings::really_construct_from_a_pointer, getenv("HOME"), nullptr), "tmwserver"); ZString config = CONFIG; if (argc > 1) config = ZString(strings::really_construct_from_a_pointer, argv[1], nullptr); read_config(config); if (chdir(workdir.c_str()) < 0) { perror("Failed to change directory"); exit(1); } PRINTF("Starting:\n"); PRINTF("* workdir: %s\n", workdir); PRINTF("* login_server: %s\n", login_server); PRINTF("* map_server: %s\n", map_server); PRINTF("* char_server: %s\n", char_server); { //make sure all possible file descriptors are free for use by the servers //if there are file descriptors higher than the max open from before the limit dropped, that's not our problem int fd = sysconf(_SC_OPEN_MAX); while (--fd > 2) if (close(fd) == 0) FPRINTF(stderr, "close fd %d\n", fd); fd = open("/dev/null", O_RDWR); if (fd < 0) { perror("open /dev/null"); exit(1); } dup2(fd, 0); dup2(fd, 1); close(fd); } while (1) { // write stuff to stderr timestamp_seconds_buffer timestamp; stamp_time(timestamp); if (!pid_login) { pid_login = start_process(login_server); FPRINTF(stderr, "[%s] forked login server: %lu\n", timestamp, static_cast<unsigned long>(pid_login)); } if (!pid_char) { pid_char = start_process(char_server); FPRINTF(stderr, "[%s] forked char server: %lu\n", timestamp, static_cast<unsigned long>(pid_char)); } if (!pid_map) { pid_map = start_process(map_server); FPRINTF(stderr, "[%s] forked map server: %lu\n", timestamp, static_cast<unsigned long>(pid_map)); } pid_t dead = wait(NULL); if (dead == -1) { perror("Failed to wait for child"); exit(1); } if (pid_login == dead) pid_login = 0; if (pid_char == dead) pid_char = 0; if (pid_map == dead) pid_map = 0; } }
/*========================================== * Disconnection of a player (account has been banned of has a status, from login-server) by [Yor] *------------------------------------------ */ static int chrif_accountban(Session *, const Packet_Fixed<0x2b14>& fixed) { dumb_ptr<map_session_data> sd; AccountId acc = fixed.account_id; if (battle_config.etc_log) PRINTF("chrif_accountban %d.\n"_fmt, acc); sd = map_id2sd(account_to_block(acc)); if (acc) { if (sd != nullptr) { sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters if (fixed.ban_not_status == 0) { // 0: change of statut, 1: ban switch (static_cast<time_t>(fixed.status_or_ban_until)) { // status or final date of a banishment case 1: // 0 = Unregistered ID clif_displaymessage(sd->sess, "Your account has 'Unregistered'."_s); break; case 2: // 1 = Incorrect Password clif_displaymessage(sd->sess, "Your account has an 'Incorrect Password'..."_s); break; case 3: // 2 = This ID is expired clif_displaymessage(sd->sess, "Your account has expired."_s); break; case 4: // 3 = Rejected from Server clif_displaymessage(sd->sess, "Your account has been rejected from server."_s); break; case 5: // 4 = You have been blocked by the GM Team clif_displaymessage(sd->sess, "Your account has been blocked by the GM Team."_s); break; case 6: // 5 = Your Game's EXE file is not the latest version clif_displaymessage(sd->sess, "Your Game's EXE file is not the latest version."_s); break; case 7: // 6 = Your are Prohibited to log in until %s clif_displaymessage(sd->sess, "Your account has been prohibited to log in."_s); break; case 8: // 7 = Server is jammed due to over populated clif_displaymessage(sd->sess, "Server is jammed due to over populated."_s); break; case 9: // 8 = No MSG (actually, all states after 9 except 99 are No MSG, use only this) clif_displaymessage(sd->sess, "Your account has not more authorised."_s); break; case 100: // 99 = This ID has been totally erased clif_displaymessage(sd->sess, "Your account has been totally erased."_s); break; default: clif_displaymessage(sd->sess, "Your account has not more authorised."_s); break; } } else if (fixed.ban_not_status == 1) { // 0: change of statut, 1: ban const TimeT timestamp = fixed.status_or_ban_until; // status or final date of a banishment timestamp_seconds_buffer buffer; stamp_time(buffer, ×tamp); AString tmpstr = STRPRINTF("Your account has been banished until %s"_fmt, buffer); clif_displaymessage(sd->sess, tmpstr); } clif_setwaitclose(sd->sess); // forced to disconnect for the change } } else { if (sd != nullptr) PRINTF("chrif_accountban failed - player not online.\n"_fmt); } return 0; }
void fread_news( NEWS * news, FILE * fp ) { const char *word; bool fMatch; for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fread_to_eol( fp ); break; case 'D': KEY( "Date", news->date, fread_string( fp ) ); break; case 'E': if( !str_cmp( word, "END" ) ) { if( !news->name ) news->name = STRALLOC( "Unknown" ); if( !news->date ) { news->date = STRALLOC( stamp_time( ) ); } if( !news->title ) news->title = STRALLOC( "News Post" ); if( news->type <= -1 ) news->type = 0; return; } break; case 'N': KEY( "Name", news->name, fread_string( fp ) ); break; case 'P': if( !str_cmp( word, "POST" ) ) { fMatch = TRUE; news->post = fread_string( fp ); break; } break; case 'T': KEY( "Title", news->title, fread_string( fp ) ); KEY( "Type", news->type, fread_number( fp ) ); break; } if( !fMatch ) bug( "fread_news(): no match: %s", word ); } }
/* olc editnews command */ void do_editnews( CHAR_DATA* ch, const char* argument) { char arg[MAX_INPUT_LENGTH]; if( IS_NPC( ch ) || !IS_IMMORTAL( ch ) ) { send_to_char( "Huh?\r\n", ch ); return; } set_char_color( AT_GREEN, ch ); switch ( ch->substate ) { default: break; case SUB_NEWS_POST: { NEWS *news = NULL; news = ( NEWS * ) ch->dest_buf; STRFREE( news->post ); news->post = copy_buffer( ch ); stop_editing( ch ); ch->substate = ch->tempnum; renumber_news( ); save_news( ); return; } break; case SUB_NEWS_EDIT: { NEWS *news = NULL; news = ( NEWS * ) ch->dest_buf; STRFREE( news->post ); news->post = copy_buffer( ch ); stop_editing( ch ); ch->substate = ch->tempnum; renumber_news( ); save_news( ); return; } break; } argument = one_argument( argument, arg ); if( arg[0] == '\0' ) { send_to_char( "Syntax: editnews addtype <name>\r\n" " editnews addnews <type> <subject>\r\n" " editnews removetype <number>\r\n" " editnews removenews <type> <number>\r\n" " editnews edittype <field> <value>\r\n" " editnews editnews <type> <number> <new subject [optional]>\r\n" " Fields being one of the following:\r\n" " name header cmd_name level\r\n", ch ); return; } if( !str_cmp( arg, "save" ) ) { renumber_news( ); save_news( ); send_to_char( "News saved.\r\n", ch ); return; } if( !str_cmp( arg, "addtype" ) ) { NEWS_TYPE *type = NULL; if( argument[0] == '\0' ) { send_to_char( "Syntax: editnews addtype <name>\r\n", ch ); return; } if( top_news_type >= NEWS_MAX_TYPES ) { send_to_char( "There are too many news types.\r\n", ch ); return; } CREATE( type, NEWS_TYPE, 1 ); type->name = STRALLOC( argument ); type->cmd_name = STRALLOC( argument ); type->vnum = top_news_type++; type->level = -1; news_command_table[type->vnum] = STRALLOC( type->cmd_name ); LINK( type, first_news_type, last_news_type, next, prev ); ch_printf( ch, "Newstype '%s' created.\r\n", argument ); return; } if( !str_cmp( arg, "removetype" ) ) { NEWS_TYPE *type = NULL; NEWS *news = NULL, *news_next; if( argument[0] == '\0' ) { send_to_char( "Syntax: editnews removetype <name>\r\n", ch ); return; } if( ( type = figure_type( argument ) ) == NULL ) { send_to_char( "Invaild newstype.\r\n", ch ); return; } UNLINK( type, first_news_type, last_news_type, next, prev ); STRFREE( type->name ); STRFREE( type->header ); STRFREE( type->cmd_name ); STRFREE( news_command_table[type->vnum] ); STRFREE( news_command_table[type->level] ); for( news = type->first_news; news; news = news_next ) { news_next = news->next; UNLINK( news, type->first_news, type->last_news, next, prev ); STRFREE( news->name ); STRFREE( news->title ); STRFREE( news->date ); STRFREE( news->post ); DISPOSE( news ); } DISPOSE( type ); --top_news_type; renumber_news( ); save_news( ); ch_printf( ch, "Newstype '%s' removed.\r\n", argument ); return; } if( !str_cmp( arg, "edittype" ) ) { char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; NEWS_TYPE *type = NULL; argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); if( arg2[0] == '\0' || arg3[0] == '\0' ) { send_to_char( "Syntax: editnews edittype <type> <field> <value>\r\n", ch ); send_to_char( "Fields being one of the following:\r\n" "name header cmd_name level\r\n", ch ); return; } if( ( type = figure_type( arg2 ) ) == NULL ) { send_to_char( "Invalid newstype.\r\n", ch ); return; } if( !str_cmp( arg3, "cmd_name" ) ) { type->cmd_name = STRALLOC( argument ); news_command_table[type->vnum] = STRALLOC( type->cmd_name ); send_to_char( "Cmd_name set.\r\n", ch ); save_news( ); return; } else if( !str_cmp( arg3, "name" ) ) { type->name = STRALLOC( argument ); send_to_char( "Name set.\r\n", ch ); save_news( ); return; } else if( !str_cmp( arg3, "level" ) ) { if( argument[0] == '\0' ) { ch_printf( ch, "%d\r\n", type->level ); return; } else type->level = atoi( argument ); send_to_char( "Level set.\r\n", ch ); save_news( ); return; } else { send_to_char( "Syntax: editnews edittype <type> <field> <value>\r\n", ch ); send_to_char( "Fields being one of the following:\r\n" "name header cmd_name level\r\n", ch ); return; } } if( !str_cmp( arg, "addnews" ) ) { char arg2[MAX_INPUT_LENGTH]; NEWS_TYPE *type = NULL; NEWS *news = NULL; argument = one_argument( argument, arg2 ); if( arg2[0] == '\0' || argument[0] == '\0' ) { send_to_char( "Syntax: editnews addnews <type> <subject>\r\n", ch ); return; } if( ( type = figure_type( arg2 ) ) == NULL ) { send_to_char( "Invaild newstype. Use 'newstypes' to get a valid listing.\r\n", ch ); return; } CREATE( news, NEWS, 1 ); news->title = STRALLOC( argument ); news->name = STRALLOC( ch->name ); news->date = STRALLOC( stamp_time( ) ); news->post = STRALLOC( "" ); /* * pop character into a writing buffer */ if( ch->substate == SUB_REPEATCMD ) ch->tempnum = SUB_REPEATCMD; else ch->tempnum = SUB_NONE; ch->substate = SUB_NEWS_POST; ch->dest_buf = news; start_editing( ch, news->post ); LINK( news, type->first_news, type->last_news, next, prev ); return; } if( !str_cmp( arg, "editnews" ) ) { char arg2[MAX_INPUT_LENGTH]; char arg3[MAX_INPUT_LENGTH]; NEWS *news = NULL; NEWS_TYPE *type = NULL; argument = one_argument( argument, arg2 ); argument = one_argument( argument, arg3 ); if( arg2[0] == '\0' ) { send_to_char( "Syntax: editnews editnews <type> <number> <new subject [optional]>\r\n", ch ); return; } /* * changed for new -newstype- indexing - 5/5/02 */ if( ( type = figure_type( arg2 ) ) == NULL ) { send_to_char( "Invalid newstype. Use 'newstypes' to get a valid listing.\r\n", ch ); return; } if( ( news = grab_news( type, arg3 ) ) == NULL ) { pager_printf_color( ch, "That's not a valid news number.\r\nUse '%s' to view the valid numbers.\r\n", type->cmd_name ); return; } /* * a changed title */ if( argument[0] != '\0' ) news->title = STRALLOC( argument ); /* * new date news was edited */ news->date = STRALLOC( stamp_time( ) ); /* * pop character into a writing buffer */ if( ch->substate == SUB_REPEATCMD ) ch->tempnum = SUB_REPEATCMD; else ch->tempnum = SUB_NONE; ch->substate = SUB_NEWS_EDIT; ch->dest_buf = news; start_editing( ch, news->post ); return; } if( !str_cmp( arg, "removenews" ) ) { char arg2[MAX_INPUT_LENGTH]; NEWS *news = NULL; NEWS_TYPE *type = NULL; argument = one_argument( argument, arg2 ); if( argument[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Syntax: editnews remove <number>\r\n", ch ); return; } /* * changed for new -newstype- indexing - 5/5/02 */ if( ( type = figure_type( arg2 ) ) == NULL ) { send_to_char( "Invalid newstype. Use 'newstypes' to get a valid listing.\r\n", ch ); return; } if( ( news = grab_news( type, argument ) ) == NULL ) { send_to_char( "Type 'news' to gain a list of the news numbers.\r\n", ch ); return; } UNLINK( news, type->first_news, type->last_news, next, prev ); STRFREE( news->name ); STRFREE( news->title ); STRFREE( news->date ); STRFREE( news->post ); DISPOSE( news ); renumber_news( ); save_news( ); send_to_char( "News item removed.\r\n", ch ); return; } }