To: "Tim A. Seever" <tseever@freenet.calgary.ab.ca> /************************************************************************* * LodMUD Beta MUD 0.0 * ************************************************************************** ************************************************************************** * (c) 1993,1994,1995 Erik Jensen, Petter N Hagen, Jan Ove Saevik, * * Bjoern Hammer, Edward Kmett, Lars Soepstad, Espen Loevaas, and * * Helger Lipmaa. * ************************************************************************** ************************************************************************** * land.c (main.c) - main() & communications module (all socket ops. here)* * Last update: 4 jan 95 - Simkin - added who daemon and authd code * *************************************************************************/ /* The headers need to be cleaned up BAD */ #ifdef __sgi__ #define _BSD_SIGNALS #ifdef MIPSEB #define _MIPSEB #endif #include <sys/endian.h> #endif #include <sys/types.h> #include <stdlib.h> #include <strings.h> #include <string.h> #include <stdio.h> #include <math.h> #ifdef __sgi__ #include <bstring.h> #include <sys/socket.h> #endif /**** No <unistd.h> or <malloc.h> on the NeXT ****/ /* #if !defined(NeXT) */ #include <stdarg.h> #include <unistd.h> /* #include <malloc.h>*/ /*#endif*/ /**************************************************/ #include <memory.h> #include <errno.h> #include <ctype.h> #include <sys/socket.h> #include <sys/wait.h> #include <netdb.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/file.h> #include <sys/ioctl.h> /*#include <netinet/in.h>*/ #include <fcntl.h> #include <signal.h> #include <limits.h> #include "structs.h" #include "mob.h" #include "obj.h" #include "utils.h" #include "interp.h" #include "handler.h" #include "db.h" #include "matrix.h" /* All over global */ int MOBtrigger = TRUE; int pulse = 0; #if defined(NeXT) /* System functions */ extern int socket( int domain, int type, int protocol ); extern int setsockopt( int s, int level, int optname, void *optval, int optlen ) ; extern int bind( int s, struct sockaddr *name, int namelen ); extern int select( int width, fd_set *readfds, fd_set *writefds, fd_set *exceptf ds, struct timeval *timeout ); extern int recv ( int s, char *buf, int len, int flags ); extern int listen( int s, int backlog ); extern int getsockname( int s, struct sockaddr *name, int *namelen ); extern int accept( int s, struct sockaddr *addr, int *addrlen ); extern int getpeername( int s, struct sockaddr *name, int *namelen ); extern int gettimeofday( struct timeval *tp, struct timezone *tzp ); #endif extern char * inet_ntoa( struct in_addr in ); char * who_list; int who_flag; #define DFLT_PORT 5000 #define DFLT_WHO_PORT 5001 #define DFLT_SPLIT_PORT 5002 #define DFLT_EVIL_PORT 5666 #define DFLT_EVIL_SPLIT 5667 #define MAX_NAME_LENGTH 15 #define MAX_HOSTNAME 256 #define OPT_USEC 250000 /* Microseconds per pass */ extern int errno; /* externs */ extern char *greetings[2]; extern struct room_data *world; extern int top_of_world; extern struct time_info_data time_info; extern char *help; extern char *glossary; extern struct ban_t *ban_list, *ncsa_list; extern char *vtcolors[]; extern struct obj_index_data *obj_index; /* local globals */ struct descriptor_data *descriptor_list, *next_to_process; int god = 0; /* all new chars are gods! */ int slow_death = 0; /* Time of shutdown, active with one of the two below */ int shut_down = 0; /* clean shutdown */ int re_boot = 0; /* start her up again ? */ int death_msg = 0; /* Warning indicator, 100 = shut her down */ char down_by[20]; /* Name of player who scheduled shutdown */ char down_reason[200]; /* Reason given for shutdown */ int spam_o_meter = 0; int maxdesc; void shutdown_request(void); void wizlogsig(void); void hupsig(void); void check_ban(struct descriptor_data *d); char * get_from_q(struct txt_q *queue); void game_loop(int control, int who_control, int split_control, int evil_control , int evil_split_control); int init_socket(int port); int new_connection(int s); #ifdef NeXT extern int connect(int s, struct sockaddr *name, int namelen); #endif int new_descriptor(int s, int x, int evil); /* socket and display type */ int process_output(struct descriptor_data *t); int process_input(struct descriptor_data *t, bool newline); #define FLAG_WRAUTH 1 /* Auth unsent yet, send if able */ #define FLAG_AUTH 2 /* Authorization in progress */ void start_auth(struct descriptor_data *d); /* Open Socket */ void send_auth(struct descriptor_data *d); /* Send to Socket */ void read_auth(struct descriptor_data *d); /* Read Auth Reply */ void close_socket(struct descriptor_data *d); void flush_queues(struct descriptor_data *d); void nonblock(int s); void parse_name(struct descriptor_data *desc, char *arg); /* int number_playing(void); */ /* extern functions */ #ifdef EXPLICIT extern int sendto(int s, const char *msg, int len, int flags, const struct sockaddr *to, int tolen); extern int recvfrom(int s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen); #endif struct char_data *make_char(char *name, struct descriptor_data *desc); void boot_db( int port ); void zone_update(void); void bleeding_update(void); void affect_update( void ); /* In spells.c */ void point_update( int pulse ); /* In limits.c */ void mobile_activity(void); void move_activity(int); void string_add(struct descriptor_data *d, char *str); void editor(struct descriptor_data *d, char *str); void perform_violence(void); void show_string(struct descriptor_data *d, char *input, bool first); void make_prompt( char *buff, struct char_data *ch) ; int main( int argc, char *argv[] ) { int pos; int port = DFLT_PORT; int who_port= DFLT_WHO_PORT; int split_port = DFLT_SPLIT_PORT; int evil_port = DFLT_EVIL_PORT; int evil_split_port = DFLT_EVIL_SPLIT; char *dir = DFLT_DIR; int control, who_control, split_control, evil_control, evil_split_control; char buf[200]; for ( pos = 1; pos < argc && argv[pos][0] == '-' ; pos++ ) { switch (*(argv[pos] + 1)) { case 'g': god = 1; wizlog( "God creation mode selected." ); break; case 'd': if ( argv[pos][2] != '\0' ) dir = &argv[pos][2]; else if (++pos < argc) dir = &argv[pos][0]; else { fprintf( stderr, "Directory arg expected after -d.\n" ); exit( 2 ); } break; case 'w': if ( argv[pos][2] != '\0' ) who_port=atoi(&argv[pos][2]); else if (++pos < argc) who_port=atoi(&argv[pos][0]); else { fprintf( stderr, "Port Arg expected after -w.\n" ); exit( 2 ); } if (who_port<1024) { fprintf( stderr, "Illegal Port\n"); exit( 2 ); } break; case 's': if ( argv[pos][2] != '\0' ) split_port=atoi(&argv[pos][2]); else if (++pos < argc) split_port=atoi(&argv[pos][0]); else { fprintf( stderr, "Port Arg expected after -s.\n" ); exit( 2 ); } if (split_port<1024) { fprintf( stderr, "Illegal Port\n"); exit( 2 ); } break; case 'e': if ( argv[pos][2] != '\0') evil_port=atoi(&argv[pos][2]); else if (++pos < argc) evil_port=atoi(&argv[pos][0]); else { fprintf( stderr, "Port Arg expected after -e.\n" ); exit( 2 ); } if (evil_port<1024) { fprintf( stderr, "Illegal Port\n"); exit( 2 ); } break; case 'f': if ( argv[pos][2] != '\0') evil_split_port=atoi(&argv[pos][2]); else if (++pos < argc) evil_split_port=atoi(&argv[pos][0]); else { fprintf( stderr, "Port Arg expected after -e.\n" ); exit( 2 ); } if (evil_split_port<1024) { fprintf( stderr, "Illegal Port\n"); exit( 2 ); } break; default: fprintf( stderr, "Unknown option -%c.\n", argv[pos][1] ); exit( 2 ); break; } } if (pos < argc) { if (!isdigit(argv[pos][0])) { fprintf( stderr, "Usage: %s [-g][-d pathname][-s split][-w who][-e e vil][-f evilsplit][port #]\n", argv[0] ); exit( 2 ); } else if ( ( port = atoi(argv[pos]) ) < 1024 ) { printf( "Illegal port #\n" ); exit( 2 ); } } wizlogf("[Who %d] [Split %d] [Port %d] [Dir %s].", who_port, split_port, por t, dir ); if ( chdir( dir ) < 0 ) { perror( dir ); exit( 2 ); } srandom( time(0) ); /* * Optional memory tuning. */ #if defined(sun) mallopt( M_MXFAST, 96 ); mallopt( M_NLBLKS, 1024 ); #endif signal( SIGPIPE, SIG_IGN ); who_control = init_socket( who_port ); split_control = init_socket( split_port ); control = init_socket( port ); evil_control = init_socket (evil_port); evil_split_control = init_socket (evil_split_port); alarm(3*60); /* If boot's longer that 3 mins, somethings wrong */ boot_db( port ); game_loop( control, who_control, split_control, evil_control, evil_split_con trol ); sprintf(buf,"%s by %s, Reason: %s\n\n",re_boot ? "Reboot" : "Shutdown",down_ by, down_reason); while ( descriptor_list ) { if (descriptor_list->character) { save_char_obj(descriptor_list->character); write_to_q(buf,&descriptor_list->output); write_to_q(VT_Normal(descriptor_list->character), &descriptor_list-> output) ; write_to_q("\n\n", &descriptor_list->output) ; } close_socket( descriptor_list ); } wizlog(buf); if (re_boot) exit(10) ; else exit(0); return 0; } /* Accept new connects, relay commands, and call 'heartbeat-funcs' */ void game_loop( int control, int who_control, int split_control, int evil_contro l, int evil_split_control ) { fd_set input_set, output_set, exc_set, who_set; int nfds; struct timeval last_time, now_time, stall_time; time_t now; static struct timeval null_time = {0, 0}; struct descriptor_data *point, *next_point; char buf[8192], *pcomm, anim[16]=""; int mask, z; bool fStall; extern const char *anim_strings[][20]; extern void do_who(struct char_data *ch, char *argument, int cmd); struct char_data who_daemon; /* Pretend the port is a player */ extern const sbyte anim_point [][4]; void mail(struct descriptor_data *d, char *arg); extern void return_pets(CHAR_DATA *ch); gettimeofday(&last_time, (struct timezone *) 0); maxdesc = control; mask = sigmask(SIGUSR1) | sigmask(SIGUSR2) | sigmask(SIGINT) | sigmask(SIGPIPE) | sigmask(SIGALRM) | sigmask(SIGTERM) | sigmask(SIGURG) | sigmask(SIGXCPU) | sigmask(SIGHUP) | sigmask(SIGVTALRM); who_flag = 0; /* Not using who hack yet */ GET_LEVEL(&who_daemon)=1; /* All other flags default off May one day read a character file, But that could cause complications */ #if 0 mallocmap(); #endif /* Main loop */ while ( (!shut_down && !re_boot) || (slow_death - time(0) >= 0)) { /* Check what's happening out there */ alarm(40); /* If not back here in 30 sec... down she goes */ /* Timeout -> SIGALRM -> Goodbye */ now = time(NULL); FD_ZERO(&who_set); FD_ZERO(&input_set); FD_ZERO(&output_set); FD_ZERO(&exc_set); FD_SET(control, &input_set); FD_SET(who_control, &input_set); FD_SET(split_control, &input_set); FD_SET(evil_control, &input_set); FD_SET(evil_split_control, &input_set); nfds=0; for (point = descriptor_list; point; point = point->next) { FD_SET(point->descriptor, &input_set); FD_SET(point->descriptor, &exc_set); FD_SET(point->descriptor, &output_set); if (point->auth_fd!=-1) { FD_SET(point->auth_fd, &input_set); if (IS_SET(point->auth_state,FLAG_WRAUTH)) FD_SET(point->auth_fd, &output_set); } } sigsetmask(mask); if ((select(maxdesc + 1, &input_set, &output_set, &exc_set, &null_time)) < 0) { perror("Select Poll: Main Port"); exit(2); } sigsetmask(0); /* Respond to whatever might be happening */ /* Who Daemon */ if (FD_ISSET(who_control, &input_set )){ who_flag=1; /** Cheesy hard-coded access to the who list */ do_who(&who_daemon,"",0); /* Load who buffer */ if ((z=new_connection(who_control))>=0) { write_to_descriptor(z,who_list); close(z); } else wizlog("who connection bombed."); wizlog("Who daemon polled."); FREE(who_list); who_flag=0; } /* New connection */ if (FD_ISSET(evil_control, &input_set) && new_descriptor(evil_control,0, 1) < 0) perror("Evil Connection"); if (FD_ISSET(evil_split_control, &input_set) && new_descriptor(evil_spli t_control,1,1) < 0) perror("Evil Split connection"); if (FD_ISSET(split_control, &input_set) && new_descriptor(split_control, 1,0) < 0) perror("Split connection"); if (FD_ISSET(control, &input_set) && new_descriptor(control,0,0) < 0) pe rror("New connection"); /* Handle Authorization */ for (point = descriptor_list; point; point = next_point) { next_point = point->next; if (FD_ISSET(point->descriptor, &exc_set)) { FD_CLR(point->descriptor, &input_set); FD_CLR(point->descriptor, &output_set); if ( point->character ) save_char_obj(point->character); close_socket(point); continue; } if (point->auth_fd==-1) continue; if (FD_ISSET(point->auth_fd, &input_set)) { read_auth(point); if (!point->auth_state) check_ban(point); } else if ((FD_ISSET(point->auth_fd, &output_set))&& IS_SET(point->auth_state,FLAG_WRAUTH)) { send_auth(point); if (!point->auth_state) check_ban(point); } } /* Read input */ for (point = descriptor_list; point; point = next_point) { next_point = point->next; if (FD_ISSET(point->descriptor, &input_set)) { if (point->showstr_point ? (process_input(point, FALSE) < 0) : (process_input(point, TRUE) < 0)) { if ( point->character ) save_char_obj( point->character ); close_socket(point); continue; } point->newline = FALSE; } else point->newline = TRUE; } /* process_commands; */ for (point = descriptor_list; point; point = next_to_process) { next_to_process = point->next; if (--(point->wait) <= 0 && (pcomm = get_from_q( &point->input )) != NULL ) { if (point->character && (point->connected == CON_PLAYING || point->connected == CON_ EDITOR) && (point->character->specials.was_in_room != NOWHERE)) { if (point->character->in_room != NOWHERE) char_from_room(point->character); char_to_room(point->character, point->character->specials.wa s_in_room); point->character->specials.was_in_room = NOWHERE; act("$n has returned.", TRUE, point->character, 0, 0, TO_ROO M); affect_total(point->character); } point->wait = 1; if (point->character) point->character->specials.timer = 0; if (point->showstr_point) show_string(point, pcomm, FALSE); else if (point->connected == CON_EDITOR) editor(point, pcomm); else if (point->connected == CON_MAILER) mail(point, pcomm); else if (point->connected != CON_PLAYING) nanny(point, pcomm); else command_interpreter(point->character, pcomm, 1); FREE( pcomm ); /*** DUMPER CORE - EJ */ /* Cheesy way to force prompts */ write_to_q( "", &point->output ); } /* else if (point->wait > 0 && point->wait_type == ANIM_NOTHING) { sprintf(anim, "\r%3d", point->wait) ; write_to_descriptor(point->descriptor,anim) ; } */ } #define anim_type (point->wait_type) #define anim_wait (point->wait-2) #define anim_num anim_point[anim_type][0] #define anim_freeze anim_point[anim_type][1] #define anim_loop anim_point[anim_type][2] #define anim_length anim_point[anim_type][3] /* give the people some prompts */ for (point = descriptor_list; point; point = next_point) { next_point = point->next; /* autosave ? */ if (FD_ISSET(point->descriptor, &output_set) && point->character && point->connected == CON_PLAYING && !point->original) if ( (time(0) - point->character->player.time.last_save) >= 300 ) { point->character->player.time.last_save = time(0) ; if(!IS_SET(point->character->specials.act,PLR_BUSY)) /* STCf("Autosaving %s.\n", point->character, GET_SHORT(poin t->character)) ; */ save_char_obj( point->character ) ; return_pets(point->character); } if (FD_ISSET(point->descriptor, &output_set) && point->output.head) { if ( point->wait <= 1 || !anim_freeze ) { /* editor */ if (point->connected == CON_EDITOR) { if (!point->showstr_point) switch(point->sub_prompt) { case 0 : write_to_q( "==>", &point->output) ;break; case 1 : write_to_q( "Old String: ", &point->output); break; case 2 : write_to_q( "New String: ", &point->output); break; default: write_to_q( "Bug? ",&point->output); break; } } else if (point->connected != CON_PLAYING) ; else if (point->showstr_point) ; /* output string */ else { make_prompt(buf, point->character) ; if ((!point->contype)||(point->connected!=CON_PLAYING)) { write_to_q(buf, &point->output) ; } else { if (strcasecmp(buf,point->last_prompt)){ /*dif*/ write_to_descriptor(point->descriptor,"\033[23;1 H\033[K"); write_to_descriptor(point->descriptor,buf); FREE(point->last_prompt); point->last_prompt=str_dup(buf); point->sending=0; sprintf(buf,"\033[24;1H%s",point->buf); write_to_descriptor(point->descriptor,buf); }; } } if (process_output(point) < 0) { if ( point->character ) save_char_obj( point->character ); close_socket(point) ; } } else if ( anim_length && anim_type >= ANIM_NOTHING && anim_type <= ANIM_PRACTICE && (anim_loop || anim_wait < anim_length)) { sprintf(anim, "\r%s", anim_strings[anim_num][anim_wait % ani m_length]) ; write_to_descriptor(point->descriptor,anim) ; } } } #undef anim_num* #undef anim_freeze #undef anim_loop #undef anim_length #undef anim_type #undef anim_wait /* See if everyone wants clock FAST. */ fStall = TRUE; /* for (point = descriptor_list; point; point = next_to_process) { if ( point->connected != CON_PLAYING ) continue; if ( point->tick_wait > 0 ) continue; fStall = TRUE; } */ /* mbox (46%) * Heartbeat. * All autonomous actions (including fighting and healing) * are subdivisions of the basic pulse at OPT_USEC interval. */ pulse++; if ( !(pulse % PULSE_ZONE) ) zone_update(); if ( !(pulse % PULSE_BLEED) ) bleeding_update(); if ( !(pulse % PULSE_WEATHER) ) weather_and_time(1); if ( !(pulse % PULSE_MOBILE) ) mobile_activity(); if ( !(pulse % PULSE_VIOLENCE) ) { if (re_boot || shut_down) night_watchman(); perform_violence(); } if ( !(pulse % PULSE_AUTOMOVE) ) move_activity( (pulse / PULSE_AUTOMOVE) % 3 ); if ( !(pulse % PULSE_POINTS) ) point_update( (pulse / PULSE_POINTS) % 10 ); if ( !(pulse % PULSE_AFFECT) ) affect_update(); #define PULSE_DEBUG_MALLOC 60 /* Every 10 sec */ /* if ( !(pulse % PULSE_DEBUG_MALLOC) ) DebugMalloc(); */ /* * Synchronize to an OPT_USEC clock. * Sleep( last_time + OPT_USEC - now ). */ if ( fStall ) { gettimeofday( &now_time, NULL ); stall_time.tv_usec = last_time.tv_usec - now_time.tv_usec + OPT_USE C; stall_time.tv_sec = last_time.tv_sec - now_time.tv_sec; if ( stall_time.tv_usec < 0 ) { stall_time.tv_usec += 1000000; stall_time.tv_sec--; } if ( stall_time.tv_usec >= 1000000 ) { stall_time.tv_usec -= 1000000; stall_time.tv_sec++; } if ( stall_time.tv_sec > 0 || ( stall_time.tv_sec == 0 && stall_time.tv_usec > 0 ) ) { if ( select( 0, NULL, NULL, NULL, &stall_time ) < 0 ) { perror( "Select stall" ); exit( 2 ); } } } gettimeofday( &last_time, NULL ); } /* } */ } char * get_from_q(struct txt_q *queue) { struct txt_block *tmp; char *dest; /* Q empty? */ if (queue->head==NULL) return NULL; tmp = queue->head; dest = tmp->text; queue->head = tmp->next; FREE( tmp ); return dest; } void write_to_q(char *txt, struct txt_q *queue) { struct txt_block *new; if( !queue || !txt ) return ; CREATE(new, struct txt_block, 1); new->text = str_dup(txt); /* Q empty? */ if (!queue->head){ new->next = NULL; queue->head = queue->tail = new; } else { queue->tail->next = new; queue->tail = new; new->next = NULL; } } /* Empty the queues before closing connection */ void flush_queues(struct descriptor_data *d) { void *tmp = get_from_q( &d->input ); FREE(tmp); tmp = get_from_q( &d->output ); FREE(tmp); } int init_socket(int port) { int s; int opt = 1; char hostname[MAX_HOSTNAME+1]; struct sockaddr_in sa; struct hostent *hp; gethostname(hostname, MAX_HOSTNAME); hp = gethostbyname(hostname); if (hp == NULL) { perror("gethostbyname"); exit(2); } sa.sin_family = hp->h_addrtype; sa.sin_port = htons(port); sa.sin_addr.s_addr = 0; sa.sin_zero[0] = 0; sa.sin_zero[1] = 0; sa.sin_zero[2] = 0; sa.sin_zero[3] = 0; sa.sin_zero[4] = 0; sa.sin_zero[5] = 0; sa.sin_zero[6] = 0; sa.sin_zero[7] = 0; s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror("Init-socket"); exit(2); } if (setsockopt (s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof (opt)) < 0) { perror ("setsockopt SO_REUSEADDR"); exit (2); } #if defined(SO_DONTLINGER) /* Time system will hold socket until it can be reused, actually not needed(?) since we have REUSEADDR above, but.. */ { struct linger ld; ld.l_onoff = 1; ld.l_linger = 1000; if (setsockopt(s, SOL_SOCKET, SO_DONTLINGER, &ld, sizeof(ld)) < 0) { perror("setsockopt SO_DONTLINGER"); exit( 2 ); } } #endif if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { perror("bind"); close(s); exit( 1 ); } listen(s, 3); return(s); } int new_connection(int s) { struct sockaddr_in isa; /* struct sockaddr peer; */ int i; int t; i = sizeof(isa); getsockname(s, (struct sockaddr *) &isa, &i); if ((t = accept(s, (struct sockaddr *) &isa, &i)) < 0) { perror("Accept"); return(-1); } nonblock(t); return(t); } /* int number_playing(void) { struct descriptor_data *d; int i; for ( i = 0, d = descriptor_list ; d ; d = d->next ) i++; return(i); } */ int workaround(struct descriptor_data *d) { struct ban_t *tmp; char *nicknamehost; nicknamehost=str_dupf("%s!%s@%s",d->name,d->user,d->host); for ( tmp = ncsa_list; tmp; tmp = tmp->next ) { if (!match( tmp->name, nicknamehost ) ) { FREE(nicknamehost); write_to_descriptor(d->descriptor,"NCSA telnet patch loaded.\n" ); return 1; } } FREE(nicknamehost); return 0; } void check_ban(struct descriptor_data *d) { struct ban_t *tmp; char *nicknamehost; nicknamehost=str_dupf("%s!%s@%s",d->name,d->user,d->host); for ( tmp = ban_list; tmp; tmp = tmp->next ) { if (!match( tmp->name, nicknamehost ) ) { FREE(nicknamehost); write_to_descriptor(d->descriptor,"You or your site have been banned from LoD.\n" ); close_socket(d); break; } } FREE(nicknamehost); } int new_descriptor(int s, int x, int evil) { int desc; struct descriptor_data *newd; int size; struct sockaddr_in sock; struct hostent *from; int get_country(char *) ; if ((desc = new_connection(s)) < 0) return (-1); if (desc > maxdesc) maxdesc = desc; /* find info */ size = sizeof(sock); if (getpeername(desc, (struct sockaddr *) &sock, &size) < 0) { perror("getpeername"); *newd->host = '\0'; } else { #if !defined(NeXT) /* There sin_addr is u_long s_addr #include <netinet/in.h> */ /* if((sock.sin_addr.s_net==199)&& (sock.sin_addr.s_host==234)&& (sock.sin_addr.s_lh==141)&& (sock.sin_addr.s_impno==2)) { close(desc); spam_o_meter++; return -1; } */ CREATE(newd, struct descriptor_data, 1); wizlogf("Socket Address: %d.%d.%d.%d", (int)*(unsigned char *)&sock.sin_addr.s_addr, (int)*(((unsigned char *)&sock.sin_addr.s_addr)+1), (int)*(((unsigned char *)&sock.sin_addr.s_addr)+2), (int)*(((unsigned char *)&sock.sin_addr.s_addr)+3)); #else wizlogf("Socket Address: %d.%d.%d.%d", sock.sin_addr.s_net, sock.sin_addr.s_host, sock.sin_addr.s_lh, sock.sin_addr.s_impno ); #endif /**** Had to take away & from sock.sin_addr ****/ /*bcopy(&sock.sin_addr,&newd->ip,sizeof(struct in_addr));*/ newd->ip=sock.sin_addr; strcpy(newd->host, inet_ntoa(sock.sin_addr)); from = gethostbyaddr( (char *) &sock.sin_addr, sizeof(sock.sin_addr), AF_INET ); if ( from ) { strncpy(newd->host, from->h_name, 49); *(newd->host + 49) = '\0'; } /* localhost.gih.no? Nah... // Helger if (!index(newd->host, '.')) strcat(newd->host, ".dorm.virginia.edu") ; */ newd->country = get_country(newd->host) ; } /* init desc data */ newd->descriptor = desc; newd->last_connected = CON_GET_NAME; newd->contype = x; newd->evil = evil; newd->connected = CON_GET_NAME; if (x) { newd->sending=1; } newd->wait = 1; *newd->buf = '\0'; strcpy(newd->user, "unknown"); newd->last_prompt = str_dupf("No Prompt"); newd->edit_length = 0; newd->edit_head = 0; newd->edit_line = 0; newd->edit_head_bu = 0; newd->edit_line_bu = 0; newd->edit_str = 0; newd->edit_func = 0; newd->edit_param = 0; newd->screen_width = 80; newd->screen_height = 20; newd->showstr_head = 0; newd->showstr_point = 0; newd->showstr_keep = FALSE; newd->newline = FALSE; newd->output.head = NULL; newd->input.head = NULL; newd->next = descriptor_list; newd->character = 0; newd->original = 0; newd->snoop.snooping = 0; newd->snoop.snoop_by = 0; newd->sx=0;newd->sy=0; newd->ox=0;newd->oy=24; /* prepend to list */ newd->next = descriptor_list; descriptor_list = newd; if (x) write_to_descriptor(desc,"\033[H\033[2JAttempting To Boot Split Scree n...\n"); else write_to_q( "\033[H\033[J", &newd->output) ; write_to_q( greetings[evil], &newd->output ); write_to_q( "By what name do you wish to be known? ", &newd->output ); if (!workaround(newd)) { start_auth(newd); } else { newd->auth_state=0; newd->auth_fd=-1; } /* Put in a authorization request ASAP */ if (!newd->auth_state) check_ban(newd); if (!newd) return (-1); return(0); } char *wrap(struct descriptor_data *t,char *pstr) { register char *i, *j, *ls, *k ; register sh_int count, rcount ; int ibuf = 0; char buf[2*MAX_STRING_LENGTH]=""; int indent=t->character?IS_SET(GET_PROMPT(t->character),PROMPT_INDENT):0; /* if ( t->newline ) { buf[ibuf++] = '\n'; } */ j=buf+ibuf ; /* Cycle thru output queue */ i=pstr, ls=0, count=0, rcount=0; while( *i && (j-buf)<MAX_STRING_LENGTH ) { if ( (*i>=32) && (*i<127) ) { /* A letter. Add one to count */ count++ ; /* Count from last '\n' */ rcount++ ; /* Word length */ } else if (*i=='\n' || *i=='\r') { /* Ok. Start count again */ count = 0 ; /* Reset Count */ rcount = 0 ; /* Reset word length */ ls = 0 ; /* No 'last-space' */ goto CheckLF ; } else if ( *i == '\33' ) { /* Escape sequence. Loop past */ while( *i && !isalpha(*i) ) /* Copy the [3;2 ... */ *j = *i, i++, j++; /* Copy... */ *j = *i; /* Copy... */ goto CheckLF ; } else goto CheckLF ; if ( *i == ' ' ) { /* Is it a space ? */ ls = j ; /* Yes.. Remember it */ rcount = 0 ; /* Reset word length */ goto CheckLF ; } if ( count > GET_WIDTH(t) ) { /* To the rescue... */ if ( ls ) { /* There is a last-space */ count = rcount; /* Reset count */ *(ls) = '\n' ; #if 0 if (indent) { ls++; j++; for (k=j;k>ls;k--) *k=*(k-1); *(ls) = 9 ; count=8; /*?*/ } #else if (indent) { j+=4; for (k=j;k>ls+4;k--) *k=*(k-4); *(++ls) = ' ' ; *(++ls) = ' ' ; *(++ls) = ' ' ; *(++ls) = ' ' ; count=4; /*?*/ } #endif } else { /* There's no ls. PAD! */ count = 0 ; /* I will _NOT_ check whether */ *(j++) = '-' ; /* words are split correctly */ *(j++) = '\n' ; /* or not! This'll have to do */ } rcount = 0 ; ls = 0 ; /* Reset last space */ goto CheckLF ; } CheckLF : /* Strip all '\r' and replac */ /* if ( !*i ) break; */ *(j++) = *(i++); } *j = 0 ; return str_dup(buf); } int process_output(struct descriptor_data *t) { int j; char *pstr, *zstr, buf[MAX_INPUT_LENGTH*10]; if ((t->last_connected!=t->connected)&&(t->connected==CON_PLAYING)&& (t->contype)){ t->sx=0;t->sy=0;t->ox=strlen(t->buf);t->oy=23;/*actual minus 1*/ t->last_connected=t->connected; t->sending=1; write_to_descriptor(t->descriptor,"\033[2J\033[24;1H"); write_to_descriptor(t->descriptor,t->buf); write_to_descriptor(t->descriptor,"\033[23;1H"); write_to_descriptor(t->descriptor,t->last_prompt); write_to_descriptor(t->descriptor,"\033[1;22r"); } else if ((t->last_connected==CON_PLAYING)&&(t->connected!=CON_PLAYING)&& (t->contype)){ write_to_descriptor(t->descriptor,"\033[1;24r\033[2J"); t->last_connected=t->connected; } while ((pstr=get_from_q(&t->output)) ) { if(!(t->contype)||(t->connected!=CON_PLAYING)) { /* Stock Connection */ if(t->newline) { /* Must send newline before new text */ write_to_descriptor(t->descriptor,"\n"); t->newline=0; } if(t->snoop.snoop_by) { /* Send to snooper */ write_to_q(VT_ch(t->character, COLOR_SNOOP), &t->snoop.snoop_by->des c->output); write_to_q(pstr, &t->snoop.snoop_by->desc->output); } zstr = wrap(t,pstr); j = write_to_descriptor( t->descriptor, zstr ); /* Just dump to desc */ FREE(zstr); FREE( pstr ); } else { if (!t->sending) { /*not already in above window at right spot */ sprintf(buf,"\033[%d;%dH",t->sy+1,t->sx+1); write_to_descriptor( t->descriptor, buf); /* Store Cursor Position, Init Window, go there */ /* Note eventually shoulder toggle last carriage return */ t->sending=1; } zstr = wrap(t,pstr); FREE(pstr); pstr=zstr; for(;*zstr;zstr++) { if (*zstr=='\n') { t->sy=MIN(21,t->sy+1);t->sx=0; } else if (*zstr=='\r') { t->sx=0; } else if (*zstr=='\b') { t->sx=MAX(0,t->sx-1); } else if (*zstr==27) { while ((*zstr)&&(!isalpha(*zstr))) zstr++; if (*zstr=='J') { t->sx=0; t->sy=0; } } else if (*zstr>31) t->sx++; if (t->sx==80) { t->sy=MIN(21,t->sy+1); t->sx=0; } } j=write_to_descriptor(t->descriptor,pstr); } FREE(pstr); } if ((t->contype)&&(t->connected==CON_PLAYING)){ sprintf(buf,"\033[24;1H%s",t->buf); write_to_descriptor( t->descriptor, buf); t->sending=0; } return j; } /* NEW --- not to lose link when buffer overflows... */ int write_to_descriptor(int desc, char *txt) { int sofar, thisround, total, e; char ntext[MAX_STRING_LENGTH]; char *ztxt; if (!txt) return 0; for (ztxt=ntext;*txt;ztxt++,txt++) if (*txt=='\n') { *ztxt='\r';ztxt++;*ztxt=*txt;} else *ztxt=*txt; *ztxt='\0'; total = strlen(ntext); sofar = 0; do { thisround = write(desc, ntext + sofar, total - sofar); e = errno; if (thisround < 0 && e != EWOULDBLOCK) { perror("Write to socket"); return(-1); } if (thisround >= 0) sofar += thisround; } while (sofar < total); return(0); } /* int old_write_to_descriptor(int desc, char *txt) { int sofar, thisround, total; total = strlen(txt); sofar = 0; do { thisround = write(desc, txt + sofar, total - sofar); if (thisround < 0) { perror("Write to socket"); return(-1); } sofar += thisround; } while (sofar < total); return(0); } */ int process_input(struct descriptor_data *t, bool newline) { int sofar, thisround, begin, squelch, i, k, flag; char tmp[MAX_INPUT_LENGTH+2], buffer[MAX_INPUT_LENGTH + 60], buf[160]; /* Still in authorization routine, buffer in use, cant take input yet! */ /* if (t->auth_state) return(0); ** WRONG **/ sofar = 0; flag = 0; begin = strlen(t->buf); /* Read in some stuff */ if ((t->connected!=t->last_connected)&&(t->connected==CON_PLAYING) &&(t->contype)) { /* set up for split screen */ t->sx=0;t->sy=0;t->ox=strlen(t->buf)%80;t->oy=23;/*actual minus 1*/ t->last_connected=t->connected; t->sending=0; write_to_descriptor(t->descriptor,"\033[2J"); write_to_descriptor(t->descriptor,"\033[23;1H"); write_to_descriptor(t->descriptor,t->last_prompt); write_to_descriptor(t->descriptor,"\033[1;22r\033[24;1H"); write_to_descriptor(t->descriptor,t->buf); } else if ((t->last_connected==CON_PLAYING)&&(t->connected!=CON_PLAYING)&& (t->contype)){ /* Get OUT of split screen *sulk* */ write_to_descriptor(t->descriptor,"\033[1;24r\033[2J"); t->last_connected=t->connected; } do { if ((t->contype)&&(t->connected==CON_PLAYING)) if (t->sending) { sprintf(buf,"\033[24;1H%s",t->buf); write_to_descriptor(t->descriptor,buf);/*return to cmd line */ t->sending=0; } /* if ((thisround = read(t->descriptor, t->buf + begin + sofar, 1, MAX_STRING_LENGTH - (begin + sofar) - 1) ) > 0){ */ if ((thisround = recv(t->descriptor, t->buf + begin + sofar, MAX_STRING_LENGTH - (begin + sofar) - 1 , 0)) > 0 ) { sofar += thisround; } else if (thisround < 0) if(errno != EWOULDBLOCK) { perror("Read1 - ERROR"); return(-1); } else { t->ox=(strlen(t->buf)%80); break; } else { wizlog("EOF encountered on socket read."); return(-1); } } while ( !ISNEWL(*(t->buf + begin + sofar - 1))); *(t->buf + begin + sofar) = 0; /* if no newline is contained in input, return without proc'ing */ for (i = begin; !ISNEWL(*(t->buf + i)); i++) if (!*(t->buf + i)) { t->ox=(strlen(t->buf)%80); return(0); } if ((t->contype) && (t->connected!=CON_EDITOR)) write_to_descriptor(t->descri ptor,"\033[24;1H\033[K"); /*clear data entry line */ /* input contains 1 or more newlines; process the stuff */ for (i = 0, k = 0; *(t->buf + i);) { if ( !ISNEWL(*(t->buf + i)) && !(flag = (k >= (MAX_INPUT_LENGTH - 2)))) /* backspace */ if(*(t->buf + i) == '\b') /* Slipped through! */ /* more than one char ? */ if (k) { if (*(tmp + --k) == '$') k--; i++; } else i++; /* no or just one char.. Skip backsp */ else if (isascii(*(t->buf + i)) && isprint(*(t->buf + i))) { *(tmp +k) = *(t->buf + i); k++; i++; } else i++; else { *(tmp + k) = 0; write_to_q(tmp, &t->input); if(t->snoop.snoop_by) { write_to_q(VT_ch(t->character, COLOR_SNOOP), &t->snoop.snoop _by->desc->output); write_to_q(tmp, &t->snoop.snoop_by->desc->output); write_to_q("\n",&t->snoop.snoop_by->desc->output); } if ((flag)&&(!t->contype)) { sprintf(buffer,"Line too long. Truncated to:\n%s\n", tmp); if (write_to_descriptor(t->descriptor, buffer) < 0) return(-1); /* skip the rest of the line */ for (; !ISNEWL(*(t->buf + i)); i++); } /* find end of entry */ for (; ISNEWL(*(t->buf + i)); i++); /* squelch the entry from the buffer */ for (squelch = 0;; squelch++) if ((*(t->buf + squelch) = *(t->buf + i + squelch)) == '\0') break; k = 0; i = 0; } } t->ox=(strlen(t->buf)%80); return(1); } void close_socket(struct descriptor_data *d) { struct descriptor_data *tmp; struct char_data *c; struct watch_data *w; extern struct char_data *character_list; if (!d->swap){ if (d->contype) write_to_descriptor(d->descriptor,"\033[1;24r"); process_output(d); close( d->descriptor ); if ( d->descriptor == maxdesc ) --maxdesc; } if (d->last_prompt) FREE(d->last_prompt); /* Forget snooping */ if (d->snoop.snooping) d->snoop.snooping->desc->snoop.snoop_by = 0; if (d->snoop.snoop_by) { STC("Your victim is no longer among us.\n",d->snoop.snoop_by ); d->snoop.snoop_by->desc->snoop.snooping = 0; } /* Purge the watch list too */ for (c=character_list;c;c=c->next) { for (w=c->watching;w;w=w->next) { if (w->watcher==d) w->watcher=0; /* fade it out, *shrugs* */ } } if (d->character) { if ( d->connected == CON_PLAYING || d->connected == CON_EDITOR ) { save_char_obj(d->character) ; act("$n has lost $s link.", TRUE, d->character, 0, 0, TO_ROOM); wizlogf("Closing link to: %s.", GET_NAME(d->character)); d->character->desc = 0; } else { wizlogf("Losing player: %s.", GET_NAME(d->character) ); free_char( d->character ); } } else wizlog( "Losing descriptor without char." ); if (d->swap) { wizlogf( "Unswapping character back to %s.",GET_NAME(d->swap)); d->character = d->swap; d->connected = CON_PLAYING; d->swap = 0; } else { if (next_to_process == d) next_to_process = next_to_process->next; if ( d == descriptor_list ) descriptor_list = descriptor_list->next; else { /* Locate the previous element */ for (tmp = descriptor_list; (tmp->next != d) && tmp; tmp = tmp->next) ; tmp->next = d->next; } FREE( d->name ); FREE( d->showstr_head ); FREE( d->edit_head ); FREE( d ); /*** DUMPER CORE ***/ } } void nonblock(int s) { if (fcntl(s, F_SETFL, FNDELAY) == -1) { perror("Noblock"); exit(2); } } void send_to_char(char *messg, struct char_data *ch) { if (ch->desc && messg) write_to_q(messg, &ch->desc->output); if (!ch->desc&&!IS_NPC(ch)) wizlogf("Null STC %s",messg); } /* attempt to authorize user--EXPERIMENTAL * start_auth * * Flag the client to show that an attempt to contact the ident server on * the client's host. The connect and subsequently the socket are all put * into 'non-blocking' mode. Should the connect or any later phase of the * identifing process fail, it is aborted and the user is given a username * of "unknown". */ void start_auth(struct descriptor_data *d) { struct sockaddr_in sock; int err;/* error & result stuffs */ int tlen; d->auth_fd = socket(AF_INET, SOCK_STREAM, 0); err = errno; if (d->auth_fd < 0 && err == EAGAIN) wizlog("Can't allocate fd for authorization check"); nonblock(d->auth_fd); /* Clone incoming host address */ tlen=sizeof(sock); getpeername(d->descriptor, (struct sockaddr *)&sock, &tlen); /*sock.sin_addr = d->ip;*/ sock.sin_port = htons(113); sock.sin_family = AF_INET; if (connect(d->auth_fd, (struct sockaddr *)&sock, sizeof(sock)) == -1 && errno != EINPROGRESS) { /* * Identd Denied */ wizlog("Unable to verify userid"); close(d->auth_fd); d->auth_fd = -1; d->auth_state = 0; /* Failure */ return; } d->auth_state |= (FLAG_WRAUTH|FLAG_AUTH); /* Successful, but not sent */ if (d->auth_fd > maxdesc) maxdesc = d->auth_fd; return; } /* * send_auth * * Send the ident server a query giving "theirport , ourport". * The write is only attempted *once* so it is deemed to be a fail if the * entire write doesn't write all the data given. This shouldnt be a * problem since the socket should have a write buffer far greater than * this message to store it in should problems arise. - Simkin */ void send_auth(struct descriptor_data *d) { struct sockaddr_in us, them; char authbuf[32]; int ulen, tlen, z; tlen = ulen = sizeof(us); if (getsockname(d->descriptor, (struct sockaddr *)&us, &ulen) || getpeername(d->descriptor, (struct sockaddr *)&them, &tlen)) { wizlog("auth getsockname error"); goto authsenderr; } /* compose request */ sprintf(authbuf, "%u , %u\r\n", (unsigned int)ntohs(them.sin_port), (unsigned int)ntohs(us.sin_port)); /* wizlogf("sending [%s] to auth port %s:113", authbuf, inet_ntoa(them.sin_addr),d->auth_fd); */ z = write(d->auth_fd, authbuf, strlen(authbuf)); if (z != strlen(authbuf)) { wizlogf("auth request, broken pipe [%d/%d]",z,errno); authsenderr: close(d->auth_fd); if (d->auth_fd == maxdesc) maxdesc--; d->auth_fd = -1; d->auth_state &= ~FLAG_AUTH; /* Failure/Continue */ } d->auth_state&= ~FLAG_WRAUTH ; /* Successfully sent request */ return; } /* * read_auth * * read the reply (if any) from the ident server we connected to. * The actual read processijng here is pretty weak - no handling of the reply * if it is fragmented by IP. */ void read_auth(struct descriptor_data *d) { char *s, *t; int len; /*length read*/ char ruser[20], system[8];/*remote userid*/ u_short remp = 0, locp = 0; /*remote port, local port*/ *system = *ruser = '\0'; /* * Nasty. Cant allow any other reads from client fd while we're * waiting on the authfd to return a full valid string. Use the * client's input buffer to buffer the authd reply. May take more * than one read. */ if ((len = read(d->auth_fd, d->abuf + d->auth_inc, sizeof(d->abuf) - 1 - d->auth_inc)) >= 0) { d->auth_inc += len; d->abuf[d->auth_inc] = '\0'; /* Null terminate!*/ } if ((len > 0) && (d->auth_inc != (sizeof(d->abuf) - 1)) && (sscanf(d->abuf, "%hd , %hd : USERID : %*[^:]: %10s", &remp, &locp, ruser) == 3)) { s = rindex(d->abuf, ':'); *s++ = '\0'; for (t = (rindex(d->abuf, ':') + 1); *t; t++) if (!isspace(*t)) break; strncpy(system, t, sizeof(system)); for (t = ruser; *s && (t < ruser + sizeof(ruser)); s++) if (!isspace(*s) && *s != ':') *t++ = *s; *t = '\0'; wizlogf("auth reply ok, incoming user: [%s]", ruser); } else if (len != 0) { if (!index(d->abuf, '\n') && !index(d->abuf, '\r')) return; wizlogf("bad auth reply: %s", d->abuf); *ruser = '\0'; } close(d->auth_fd); if (d->auth_fd == maxdesc) --maxdesc; d->auth_inc = 0; *d->abuf='\0'; d->auth_fd = -1; d->auth_state = 0; strncpy(d->user, ruser, sizeof(d->user)); return; } void STCf( const char *format, struct char_data *ch, ... ) { va_list ap; char buf[640] ; #if !defined(NeXT) va_start(ap,ch); #else va_start(ap, format) ; #endif vsprintf(buf, format, ap) ; STC(buf, ch); } void STRf( const char *format, int room, ... ) { va_list ap; char buf[640] ; va_start(ap, room) ; vsprintf(buf, format, ap) ; send_to_room(buf, room); } void STAf( const char *format, ... ) { va_list ap; char buf[640] ; va_start(ap, format) ; vsprintf(buf, format, ap) ; send_to_all(buf); } void send_to_all(char *messg) { struct descriptor_data *i; if (messg) for (i = descriptor_list; i; i = i->next) if (!i->connected && !IS_SET(i->character->specials.act, PLR_BUSY)) write_to_q(messg, &i->output); } void send_to_all_regardless(char *messg) { struct descriptor_data *i; if (messg) for (i = descriptor_list; i; i = i->next) write_to_q(messg, &i->output); } void send_to_outdoor(char *messg) { struct descriptor_data *i; if (messg) for (i = descriptor_list; i; i = i->next) if (!i->connected && !IS_SET(i->character->specials.act, PLR_BUSY)) if (IS_OUTSIDE(i->character) && i->connected == CON_PLAYING) write_to_q(messg, &i->output); } void send_to_room(char *messg, int room) { struct char_data *i; if (messg) for (i = ROOM_PEOPLE(room); i; i = i->next_in_room) if (i->desc && !IS_SET(i->specials.act, PLR_BUSY)) if (i->desc->connected == CON_PLAYING) write_to_q(messg, &i->desc->output); } void actf(char * str, int hide_invisible, struct char_data *ch, struct obj_data *obj, void * vict_obj, int type, ...) { va_list ap; char buf[640] ; va_start(ap, type) ; vsprintf(buf, str, ap) ; act(buf,hide_invisible,ch,obj,vict_obj,type); } void act(char * str, int hide_invisible, struct char_data *ch, struct obj_data *obj, void * vict_obj, int type) { void mprog_act_trigger( char *buf, CHAR_DATA *mob, CHAR_DATA *ch, OBJ_DATA *obj, CHAR_DATA *vict, OBJ_DATA *v_obj); int x=0; struct parasite_data *p; int z; struct char_data *to; char *tstr; struct watch_data *w; register char *strp, *point, *i = NULL; /* int c=0; */ char buf[MAX_STRING_LENGTH]; MOBtrigger=TRUE; if ( !str || !*str ) return; if (type == TO_VICT) to = (struct char_data *) vict_obj; else if (type == TO_CHAR) to = ch; else if (GET_INROOM(ch)!=NOWHERE) to = ROOM_PEOPLE(GET_INROOM(ch)); else { wizlogf("Action '%s' nowhere.\n",buf); return; } for (; to; to = to->next_in_room) { if (IS_SET(to->specials.act, PLR_BUSY)) continue ; if ( (to->desc ? to->desc->connected == CON_PLAYING : 1) && ((to != ch) || (type == TO_CHAR)) && (CAN_SEE(to, ch) || !hide_invisible || (type == TO_VICT)) && AWAKE(to) && !((type == TO_NOTVICT) && (to == (struct char_data *) vict_obj))) { for (strp = str, point = buf;;) if (*strp == '$') { switch (*(++strp)) { case 'n': i = PERS(ch, to); break; case 'N': i = PERS((struct char_data *) vict_obj, to); b reak; case 'm': i = HMHR(ch); break; case 'M': i = HMHR((struct char_data *) vict_obj); break ; case 's': i = HSHR(ch); break; case 'S': i = HSHR((struct char_data *) vict_obj); break ; case 'e': i = HSSH(ch); break; case 'E': i = HSSH((struct char_data *) vict_obj); break ; case 'o': i = OBJN(obj, to); break; case 'O': i = OBJN((struct obj_data *) vict_obj, to); br eak; case 'p': i = OBJS(obj, to); break; case 'P': i = OBJS((struct obj_data *) vict_obj, to); br eak; case 'a': i = SANA(obj); break; case 'A': i = SANA((struct obj_data *) vict_obj); break; case 'T': i = (char *) vict_obj; break; case 'F': i = fname((char *) vict_obj); break; case '$': i = "$"; break; default : wizlogf("Illegal $-code to act(): %s", str); b reak; } if (i == NULL) {if (x) FREE(str);return;} while ( ( *point = *(i++) ) != '\0' ) ++point; ++strp; } else if (!(*(point++) = *(strp++))) break; *(--point) = '\n'; *(++point) = '\0'; if (to->desc) write_to_q(CAP(buf), &to->desc->output); if (MOBtrigger) mprog_act_trigger( buf, to, ch, obj, (struct char_da ta *)vict_obj, (struct obj_data *) vict_obj ); } if ((type == TO_VICT) || (type == TO_CHAR)) { MOBtrigger = TRUE; return; } } tstr=str; #if 0 str=str_dupf("%s%s",ROOM_PREFIX(GET_INROOM(ch))?ROOM_PREFIX(GET_INROOM(ch)):"", str); for (p=ROOM_PARASITE(GET_INROOM(ch));p;p=p->next) { z=real_room(p->room); if (z!=NOWHERE) for (to=ROOM_PEOPLE(z); to; to = to->next_in_room) { if (IS_SET(to->specials.act, PLR_BUSY)) continue ; if ( (to->desc ? to->desc->connected == CON_PLAYING : 1) && ((to != ch) || (type == TO_CHAR)) && (CAN_SEE(to, ch) || !hide_invisible || (type == TO_VICT)) && AWAKE(to) && !((type == TO_NOTVICT) && (to == (struct char_data *) vict_obj))) { for (strp = str, point = buf;;) if (*strp == '$') { switch (*(++strp)) { case 'n': i = PERS(ch, to); break; case 'N': i = PERS((struct char_data *) vict_obj, to); b reak; case 'm': i = HMHR(ch); break; case 'M': i = HMHR((struct char_data *) vict_obj); break ; case 's': i = HSHR(ch); break; case 'S': i = HSHR((struct char_data *) vict_obj); break ; case 'e': i = HSSH(ch); break; case 'E': i = HSSH((struct char_data *) vict_obj); break ; case 'o': i = OBJN(obj, to); break; case 'O': i = OBJN((struct obj_data *) vict_obj, to); br eak; case 'p': i = OBJS(obj, to); break; case 'P': i = OBJS((struct obj_data *) vict_obj, to); br eak; case 'a': i = SANA(obj); break; case 'A': i = SANA((struct obj_data *) vict_obj); break; case 'T': i = (char *) vict_obj; break; case 'F': i = fname((char *) vict_obj); break; case '$': i = "$"; break; default : wizlogf("Illegal $-code to act(): %s", str); b reak; } if (i == NULL) {if (x) FREE(str);return;} while ( ( *point = *(i++) ) != '\0' ) ++point; ++strp; } else if (!(*(point++) = *(strp++))) break; *(--point) = '\n'; *(++point) = '\0'; if (to->desc) write_to_q(CAP(buf), &to->desc->output); /* if (MOBtrigger) mprog_act_trigger( buf, to, ch, obj, vict_obj ); */ } if ((type == TO_VICT) || (type == TO_CHAR)) { MOBtrigger = TRUE; FREE(str); return; } } } for (to=ROOM_PEOPLE(GET_INROOM(ch));to;to=to->next) { for (w=to->watching; w; w= w->next) { for (strp = str, point = buf;;) if (*strp == '$') { switch (*(++strp)) { case 'n': i = PERS(ch, to); break; case 'N': i = PERS((struct char_data *) vict_obj, to); b reak; case 'm': i = HMHR(ch); break; case 'M': i = HMHR((struct char_data *) vict_obj); break ; case 's': i = HSHR(ch); break; case 'S': i = HSHR((struct char_data *) vict_obj); break ; case 'e': i = HSSH(ch); break; case 'E': i = HSSH((struct char_data *) vict_obj); break ; case 'o': i = OBJN(obj, to); break; case 'O': i = OBJN((struct obj_data *) vict_obj, to); br eak; case 'p': i = OBJS(obj, to); break; case 'P': i = OBJS((struct obj_data *) vict_obj, to); br eak; case 'a': i = SANA(obj); break; case 'A': i = SANA((struct obj_data *) vict_obj); break; case 'T': i = (char *) vict_obj; break; case 'F': i = fname((char *) vict_obj); break; case '$': i = "$"; break; default : wizlogf("Illegal $-code to act(): %s", str); b reak; } if (i == NULL) {if (x) FREE(str);return;} while ( ( *point = *(i++) ) != '\0' ) ++point; ++strp; } else if (!(*(point++) = *(strp++))) break; *(--point) = '\n'; *(++point) = '\0'; if (to->desc) write_to_q(CAP(buf), &w->watcher->output); } } #endif #if 0 if (!IS_ONMATRIX(ch)) { for (c=0;c<MAX_EXITS;c++) if (EXIT(ch,c)) { if ((CAN_GO(ch,c)) && (EXIT(ch,c)->theysee)){ FREE(str); str=str_dupf("%s%s",EXIT(ch,c)->theysee,tstr); z=real_room(EXIT(ch,c)->to_room); if (z != NOWHERE) for (to=ROOM_PEOPLE(z); to; to = to->next_in_room) { if (IS_SET(to->specials.act, PLR_BUSY)) continue ; if ( (to->desc ? to->desc->connected == CON_PLAYING : 1) && ((to != ch) || (type == TO_CHAR)) && (CAN_SEE(to, ch) || !hide_invisible || (type == TO_VICT)) && AWAKE(to) && !((type == TO_NOTVICT) && (to == (struct char_data *) vict_obj))) { for (strp = str, point = buf;;) if (*strp == '$') { switch (*(++strp)) { case 'n': i = PERS(ch, to); break; case 'N': i = PERS((struct char_data *) vict_obj, to); b reak; case 'm': i = HMHR(ch); break; case 'M': i = HMHR((struct char_data *) vict_obj); break ; case 's': i = HSHR(ch); break; case 'S': i = HSHR((struct char_data *) vict_obj); break ; case 'e': i = HSSH(ch); break; case 'E': i = HSSH((struct char_data *) vict_obj); break ; case 'o': i = OBJN(obj, to); break; case 'O': i = OBJN((struct obj_data *) vict_obj, to); br eak; case 'p': i = OBJS(obj, to); break; case 'P': i = OBJS((struct obj_data *) vict_obj, to); br eak; case 'a': i = SANA(obj); break; case 'A': i = SANA((struct obj_data *) vict_obj); break; case 'T': i = (char *) vict_obj; break; case 'F': i = fname((char *) vict_obj); break; case '$': i = "$"; break; default : wizlogf("Illegal $-code to act(): %s", str); b reak; } if (i == NULL) {if (x) FREE(str);return;} while ( ( *point = *(i++) ) != '\0' ) ++point; ++strp; } else if (!(*(point++) = *(strp++))) break; *(--point) = '\n'; *(++point) = '\0'; if (to->desc) write_to_q(CAP(buf), &to->desc->output); /* if (MOBtrigger) mprog_act_trigger( buf, to, ch, obj, vict_obj ); */ } if ((type == TO_VICT) || (type == TO_CHAR)) { MOBtrigger = TRUE; FREE(str); return; } } } } } FREE(str); #endif MOBtrigger = TRUE; } void night_watchman(void) { int secs; char buf[200]; secs = slow_death - time(0); if (secs > 600) return; if (death_msg < 1 && secs < 600 && secs > 120) { sprintf(buf,"Armageddon shouts \"%s is closing the Realm down in less than 1 0 minutes%s.\"\n", down_by,re_boot?" for reboot":""); send_to_all(buf); death_msg = 1; return; } if (death_msg < 2 && secs < 120 && secs > 60) { sprintf(buf,"Armageddon shouts \"%s in less than 2 minutes!\"\n", re_boot ? "Reboot" : "Shutdown"); send_to_all_regardless(buf); death_msg = 2; return; } if (death_msg < 3 && secs < 60 && secs > 10) { sprintf(buf,"Armageddon shouts \"Less than 1 minute to %s!\"\n", re_boot ? "Reboot" : "Shutdown"); send_to_all_regardless(buf); death_msg = 3; return; } if (death_msg < 4 && secs < 10 && secs > 5) { sprintf(buf,"Armageddon shouts \"Ten seconds to %s!!!\"\n", re_boot ? "Reboo t" : "Shutdown"); send_to_all_regardless(buf); death_msg = 4; return; } if (death_msg < 5 && secs < 5) { sprintf(buf,"Armageddon shouts \"Five seconds to %s!!!\"\n", re_boot ? "Rebo ot" : "Shutdown"); send_to_all_regardless(buf); death_msg = 5; return; } if (death_msg < 6 && secs < 2) { sprintf(buf,"Armageddon shouts \"One second to %s!!!\"\n", re_boot ? "Reboot " : "Shutdown"); send_to_all_regardless(buf); death_msg = 6; return; } /* May one day use this to schedule reboots at given time of day... PNH long tc; struct tm *t_info; extern int shut_down; tc = time(0); t_info = localtime(&tc); if ((t_info->tm_hour == 8) && (t_info->tm_wday > 0) && (t_info->tm_wday < 6) ) { if (t_info->tm_min > 50) { wizlog("Leaving the scene for the serious folks."); send_to_all("Closing down. Thank you for flying the Land.\n"); shut_down = 1; } else if (t_info->tm_min > 40) send_to_all("ATTENTION: The Land will shut down in 10 minutes.\n"); else if (t_info->tm_min > 30) send_to_all("Warning: The Land will close in 20 minutes.\n"); } */ }