#ifdef SYSV
#include <sys/file.h>
#endif
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <sys/time.h>
#include <fcntl.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "handler.h"
#include "db.h"
#define DFLT_PORT 2150 /* default port */
#define MAX_NAME_LENGTH 12
#define MAX_HOSTNAME 256
#define OPT_USEC 100000
#define MAXFDALLOWED 200
#define MAXOCLOCK 500
extern int errno;
extern struct room_data *world;
extern int top_of_world;
extern struct time_info_data time_info;
extern char help[];
extern int reboottime;
/* local globals */
struct descriptor_data *descriptor_list, *next_to_process;
jmp_buf env;
int s;
int slow_death = 0;
int shutdowngame = 0;
int shutdownwarn = 0;
int maxdesc, avail_descs;
int tics = 0;
int newsflashflag = 0;
int nonewplayers = 0;
int nonewconnect = 0;
int nostealflag = 1;
int nokillflag = 1;
int noshoutflag = 0;
int mischance = 20;
int hitchance = 80;
int bobflag=0;
int jokecount=10;
int timeoflastconnect = 0;
int pcdeaths=0,mobdeaths=0;
int grand_total = 0;
int melsnumber = -1;
int bytetotal[256];
struct char_data *out_char; /* SLUG_CHANGE 11-17-96 */
int baddoms;
char baddomain[BADDOMS][BADSTRLEN];
int newbeedoms;
char newbeedomain[BADDOMS][BADSTRLEN];
char *bobname;
struct descriptor_data *xo;
int freq_ct[300];
void logsig(int sig);
void hupsig(int sig);
void shutdown_request(int sig);
void checkpointing(int sig);
int get_from_q(struct txt_q *queue, char *dest);
/* write_to_q is in comm.h for the macro */
int run_the_game(int port);
int game_loop(int s);
int init_socket(int port);
int new_connection(int s);
int new_descriptor(int s);
int process_output(struct descriptor_data *t);
int process_input(struct descriptor_data *t);
void close_sockets(int s);
void close_socket(struct descriptor_data *d);
struct timeval timediff(struct timeval *a, struct timeval *b);
void flush_queues(struct descriptor_data *d);
void nonblock(int s);
void parse_name(struct descriptor_data *desc, char *arg);
void freaky(struct descriptor_data *d);
/* extern fcnts */
struct char_data *make_char(char *name, struct descriptor_data *desc);
void boot_db(void);
void zone_update(void);
void affect_update( void ); /* In spells.c */
void point_update( void ); /* In limits.c */
void free_char(struct char_data *ch);
void log(char *str);
void mobile_activity(void);
void string_add(struct descriptor_data *d, char *str);
void perform_violence(void);
void stop_fighting(struct char_data *ch);
void show_string(struct descriptor_data *d, char *input);
void save_char(struct char_data *ch, sh_int load_room);
/* *********************************************************************
* main game loop and related stuff *
********************************************************************* */
int sigct=0;
int main(int argc, char **argv)
{
int i,port;
char buf[512];
char *dir;
port = DFLT_PORT;
dir = DFLT_DIR;
newbeedoms=0;
baddoms=1;
strcpy(baddomain[0],"141.109.20.61");
if (argc > 1) {
if (!isdigit(*argv[1])) {
fprintf(stderr, "Usage: %s [ port # ]\n",
argv[0]);
exit(0);
} else if ((port = atoi(argv[1])) <= 1024) {
fprintf(stderr,"Illegal port #\n");
exit(0);
}
}
bobname=(char *)strdup("Bob");
if (chdir(dir) < 0) {
perror("chdir");
exit(0);
}
for(i=0;i<256;i++)
bytetotal[i]=0;
reboottime=time(0);
srand48(reboottime);
sprintf(buf,"Boottime = %d",reboottime);
log(buf);
run_the_game(port);
return(0);
}
int run_the_game(int port)
{
struct descriptor_data *point,*next_point;
void signal_setup(void);
void saveallplayers();
descriptor_list = NULL;
signal_setup();
do {
s = init_socket(port);
if(s < 0) exit(0);
} while(s < 0);
boot_db();
log("Entering game loop.");
game_loop(s);
saveallplayers();
close_sockets(s);
log("Normal termination of game.");
}
void saveallplayers()
{
struct descriptor_data *pt, *npt;
for (pt = descriptor_list; pt; pt = npt) {
npt = pt->next;
if(pt->connected == CON_PLYNG) {
if(pt->character)
stash_char(pt->character,0);
} else {
if(pt->character){
if(pt->character->specials.timer > 20){
log("Tried auto-closing a non-playing descriptor.");
close_socket(pt);
}
}
}
}
}
fd_set input_set, output_set, exc_set;
int game_loop(int s)
{
int tmp_room, old_len;
struct timeval last_time, now, timespent, timeout, null_time;
static struct timeval opt_time;
char comm[MAX_INPUT_LENGTH];
struct descriptor_data *t, *point, *next_point;
int pulse = 0, testmask, mask, xoclock = 0, flag;
char prmpt[64];
null_time.tv_sec = 0;
null_time.tv_usec = 0;
opt_time.tv_usec = OPT_USEC; /* Init time values */
opt_time.tv_sec = 0;
gettimeofday(&last_time, (struct timezone *) 0);
maxdesc = s;
avail_descs = MAXFDALLOWED;
/*
mask = sigmask(SIGUSR1) | sigmask(SIGUSR2) | sigmask(SIGINT) |
sigmask(SIGBUS ) | sigmask(SIGSEGV) | sigmask(SIGTRAP) |
sigmask(SIGPIPE) | sigmask(SIGALRM) | sigmask(SIGTERM) |
sigmask(SIGURG ) | sigmask(SIGXCPU) | sigmask(SIGHUP);
testmask = sigmask(SIGBUS) | sigmask(SIGSEGV);
*/
/* Main loop */
while(!shutdowngame) {
setjmp(env);
if(shutdowngame) continue;
if(shutdownwarn){
if(shutdownwarn==1)
shutdowngame=1;
else
--shutdownwarn;
}
/* Check what's happening out there */
FD_ZERO(&input_set);
FD_ZERO(&output_set);
FD_ZERO(&exc_set);
FD_SET(s, &input_set);
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);
}
/* check out the time */
gettimeofday(&now, (struct timezone *) 0);
timespent = timediff(&now, &last_time);
timeout = timediff(&opt_time, ×pent);
last_time.tv_sec = now.tv_sec + timeout.tv_sec;
last_time.tv_usec = now.tv_usec + timeout.tv_usec;
if (last_time.tv_usec >= 1000000) {
last_time.tv_usec -= 1000000;
last_time.tv_sec++;
}
extern int sigsetmask (int __mask) __THROW __attribute_deprecated__;
if(timeout.tv_usec)
if(select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &timeout) < 0) {
perror("Select sleep");
exit(1);
}
if(select(maxdesc+1, &input_set, &output_set, &exc_set, &null_time) < 0) {
perror("Select poll");
exit(0);
}
extern int sigsetmask (int __mask) __THROW __attribute_deprecated__;
if(!nonewconnect)
if(FD_ISSET(s, &input_set))
new_descriptor(s);
for(point = descriptor_list; point; point = next_point) {
next_point = point->next;
if(FD_ISSET(point->descriptor, &exc_set)) {
freaky(point);
FD_CLR(point->descriptor, &input_set);
FD_CLR(point->descriptor, &output_set);
}
}
for (point = descriptor_list; point; point = next_point) {
next_point = point->next;
if (FD_ISSET(point->descriptor, &input_set))
if (process_input(point) < 0) {
FD_CLR(point->descriptor, &input_set);
FD_CLR(point->descriptor, &output_set);
if (point->connected == CON_PLYNG) {
stash_char(point->character,0);
}
close_socket(point);
}
}
/* process_commands; */
if(sigct < 10)
for (point = descriptor_list; point; point = next_to_process) {
next_to_process = point->next;
if ((--(point->wait) <= 0) && get_from_q(&point->input, comm)) {
if(point->character && (point->connected == CON_PLYNG) &&
(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.was_in_room);
point->character->specials.was_in_room = NOWHERE;
act("$n has returned.", TRUE, point->character, 0, 0, TO_ROOM);
}
point->wait = 1;
if (point->character)
point->character->specials.timer = 0;
point->prompt_mode = 1;
if (point->str)
string_add(point, comm);
else if (!point->connected)
if (point->showstr_point)
show_string(point, comm);
else {
point->wait += command_interpreter(point->character, comm);
++point->ncmds;
}
else
nanny(point, comm);
}
}
for (point = descriptor_list; point; point = next_point) {
next_point = point->next;
if (FD_ISSET(point->descriptor, &exc_set)) {
freaky(point);
FD_CLR(point->descriptor, &input_set);
FD_CLR(point->descriptor, &output_set);
}
}
for (point = descriptor_list; point; point = next_point) {
next_point = point->next;
xo=point;
if (FD_ISSET(point->descriptor, &output_set) && point->output.head)
if((flag=process_output(point)) < 0){
FD_CLR(point->descriptor, &input_set);
FD_CLR(point->descriptor, &output_set);
if (point->connected == CON_PLYNG) {
stash_char(point->character,0);
}
close_socket(point);
} else
point->prompt_mode = flag;
}
/* give the people some prompts */
++xoclock;
if (xoclock == MAXOCLOCK) {
xoclock=0;
}
for (point = descriptor_list; point; point = point->next){
if((!point->connected) && (!point->original) &&
(GET_LEVEL(point->character)<IMO) && (point->descriptor==xoclock)){
save_char(point->character,NOWHERE);
stash_char(point->character,0);
}
if (point->prompt_mode) {
out_char = point->character; /* SLUG_CHANGE 11-17-96 */
if (point->str)
write_to_descriptor(point->descriptor, "] ");
else if (!point->connected)
if (point->showstr_point)
write_to_descriptor(point->descriptor,
"--<< Press return >>--");
else {
if(GET_LEVEL(point->character) < IMO){
if(point->character->specials.fighting){
sprintf(prmpt, "\[%d,%d,%d](%d) ",
GET_HIT(point->character),
GET_MANA(point->character),
GET_MOVE(point->character),
GET_HIT(point->character->specials.fighting));
} else {
sprintf(prmpt, "\[%d,%d,%d] ",
GET_HIT(point->character),GET_MANA(point->character),
GET_MOVE(point->character));
}
} else {
sprintf(prmpt, "\[%d] ",
world[point->character->in_room].number);
}
write_to_descriptor(point->descriptor, prmpt);
}
point->prompt_mode = 0;
}
}
pulse++;
if (!(pulse % PULSE_ZONE))
zone_update();
if (!(pulse % PULSE_MOBILE))
mobile_activity();
if (!(pulse % PULSE_VIOLENCE))
perform_violence();
if (!(pulse % SECS_PER_MUD_HOUR)){
weather_and_time(1);
affect_update();
point_update();
}
if (pulse >= 2400) {
pulse = 0;
/* zapper(); */
}
tics++;
}
}
/*
zapper shuts down the game on Mon-Fri at 7 am EST
*/
zapper()
{
int dow,tod,t;
t=time(0)-18000;
dow=((t/86400)+5)%7;
tod=(t%86400)/60;
if(dow >= 2){
if(tod > 900) return;
if(tod > 390) send_to_all("The game will shut down soon.\n\r");
if(tod >= 420){
shutdowngame=1;
if(getppid() > 1)
kill(getppid(),9);
}
}
}
/* ******************************************************************
* general utility stuff (for local use) *
****************************************************************** */
int get_from_q(struct txt_q *queue, char *dest)
{
struct txt_block *tmp;
/* Q empty? */
if (!queue->head)
return(0);
tmp = queue->head;
strcpy(dest, queue->head->text);
queue->head = queue->head->next;
free(tmp->text);
free(tmp);
return(1);
}
void write_to_q(char *txt, struct txt_q *queue)
{
struct txt_block *new;
CREATE(new, struct txt_block, 1);
CREATE(new->text, char, strlen(txt) + 1);
strcpy(new->text, txt);
if (!queue->head) {
new->next = NULL;
queue->head = queue->tail = new;
} else {
queue->tail->next = new;
queue->tail = new;
new->next = NULL;
}
}
struct timeval timediff(struct timeval *a, struct timeval *b)
{
struct timeval rslt, tmp;
tmp = *a;
if ((rslt.tv_usec = tmp.tv_usec - b->tv_usec) < 0)
{
rslt.tv_usec += 1000000;
--(tmp.tv_sec);
}
if ((rslt.tv_sec = tmp.tv_sec - b->tv_sec) < 0)
{
rslt.tv_usec = 0;
rslt.tv_sec = 0;
}
return(rslt);
}
/* Empty the queues before closing connection */
void flush_queues(struct descriptor_data *d)
{
char dummy[MAX_STRING_LENGTH];
while (get_from_q(&d->output, dummy));
while (get_from_q(&d->input, dummy));
}
/* ******************************************************************
* socket handling *
****************************************************************** */
int init_socket(int port)
{
int s;
char *opt;
char hostname[MAX_HOSTNAME+1];
struct sockaddr_in sa;
struct hostent *hp;
struct linger ld;
bzero((char *)&sa, sizeof(struct sockaddr_in));
gethostname(hostname, MAX_HOSTNAME);
log(hostname);
hp = gethostbyname(hostname);
if (hp == NULL) {
perror("gethostbyname");
exit(1);
}
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons(port);
s = socket(AF_INET,SOCK_STREAM,0);
if(s < 0) {
perror("Init-socket");
exit(1);
}
if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *) &opt, sizeof(opt)) < 0){
perror ("setsockopt REUSEADDR");
exit (1);
}
/*
ld.l_onoff = 0; ld.l_linger = 0;
if (setsockopt(s, SOL_SOCKET, SO_LINGER, &ld, sizeof(ld)) < 0) {
perror("setsockopt LINGER");
exit(1);
}
*/
if (bind(s,(struct sockaddr *) &sa, sizeof(sa)) < 0) {
perror("bind");
close(s);
return(-1);
}
listen(s, 3);
return(s);
}
int new_connection(int s)
{
struct sockaddr_in isa;
/* struct sockaddr peer; */
int i;
int t;
char buf[100];
i = sizeof(isa);
getsockname(s, (struct sockaddr *) &isa, &i);
if ((t = accept(s, (struct sockaddr *) &isa, &i)) < 0) {
return(-1);
}
nonblock(t);
return(t);
}
int new_descriptor(int s)
{
int desc;
struct descriptor_data *newd;
int i,size;
struct sockaddr_in sock;
struct hostent *from;
char buf[10];
if ((desc = new_connection(s)) < 0)
return (-1);
bytetotal[desc]=0;
timeoflastconnect=time(0);
size = sizeof(sock);
if(getpeername(desc,(struct sockaddr *)&sock,&size) < 0){
*newd->host = 0;
close(desc);
return(-1);
} else {
if(unfriendly_domain((char *)inet_ntoa(sock.sin_addr),baddomain,baddoms)){
close(desc);
return(-1);
}
}
CREATE(newd, struct descriptor_data, 1);
strncpy(newd->host,(char *)inet_ntoa(sock.sin_addr),16);
if((maxdesc+1) >= avail_descs){
close(desc);
flush_queues(newd);
free((char *)newd);
return(0);
} else
if (desc > maxdesc)
maxdesc = desc;
newd->ncmds = 0; newd->contime = time(0);
newd->descriptor = desc;
newd->connected = 1;
newd->wait = 1;
newd->prompt_mode = 0;
*newd->buf = '\0';
newd->str = 0;
newd->showstr_head = 0;
newd->showstr_point = 0;
*newd->last_input= '\0';
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;
/* prepend to list */
descriptor_list = newd;
SEND_TO_Q(GREETINGS, newd);
if(nonewplayers){
SEND_TO_Q("WARNING:\n\r",newd);
SEND_TO_Q("No NEW characters are being accepted right now.\n\r\n\r",newd);
}
SEND_TO_Q("By what name do you wish to be known? ", newd);
return(0);
}
unfriendly_domain(h,list,listlen)
char *h;
char list[BADDOMS][BADSTRLEN];
int listlen;
{
int i;
for(i=0;i<listlen;++i){
if(strncmp(h,list[i],strlen(list[i]))==0){
return(1);
}
}
return(0);
}
int process_output(struct descriptor_data *t)
{
char i[MAX_STRING_LENGTH + 1];
int iter=0;
out_char = t->character; /* SLUG_CHANGE 11-17-96 */
if(!t->prompt_mode && !t->connected)
if (write_to_descriptor(t->descriptor, "\n\r") < 0)
return(-1);
while(get_from_q(&t->output, i)){
if(t->snoop.snoop_by) {
write_to_q("> ",&t->snoop.snoop_by->desc->output);
write_to_q(i,&t->snoop.snoop_by->desc->output);
}
if (write_to_descriptor(t->descriptor, i))
return(-1);
}
if(!t->connected && !(t->character && !IS_NPC(t->character) &&
IS_SET(t->character->specials.act, PLR_COMPACT)))
if(write_to_descriptor(t->descriptor, "\n\r") < 0)
return(-1);
return(1);
}
#include <sys/ioctl.h>
int write_to_descriptor(int desc, char *txt)
{
int sofar, thisround, total;
int w,x,y,z;
char buf[256];
static int max=0;
total = strlen(txt);
/*
if(total > max){
sprintf(buf,"Output Max = %d.",max=total);
log(buf);
}
*/
sofar = 0;
do {
/*
ioctl(desc,SIOCGPGRP,&w);
ioctl(desc,SIOCATMARK,&x);
ioctl(desc,SIOCGHIWAT,&y);
ioctl(desc,SIOCGLOWAT,&z);
sprintf(buf,"IOCTL: %d %d %x %x",w,x,y,z);
log(buf);
*/
thisround = write(desc, txt + sofar, total - sofar);
if (thisround < 0) {
perror("Write to socket");
return(-1);
} else if(thisround==0) {
} else {
sofar += thisround;
}
} while (sofar < total);
grand_total += sofar;
bytetotal[desc] += sofar;
if(out_char)
out_char->specials.outbytes += sofar; /* SLUG_CHANGE 11-17-96 */
return(0);
}
int process_input(struct descriptor_data *t)
{
int sofar, thisround, begin, squelch, i, k, flag;
char tmp[MAX_STRING_LENGTH],buffer[MAX_STRING_LENGTH];
sofar = 0;
flag = 0;
begin = strlen(t->buf);
/* Read in some stuff */
do {
if ((thisround = read(t->descriptor, t->buf + begin + sofar,
MAX_INPUT_LENGTH - (begin + sofar) - 1)) > 0)
sofar += thisround;
else
if (thisround < 0)
if(errno != EWOULDBLOCK) {
perror("Read1 - ERROR");
return(-1);
} else
break;
else {
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))
return(0);
if(t->character) /* SLUG_CHANGE 11-17-96 */
t->character->specials.inbytes += sofar;
/* 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))))
if(*(t->buf + i) == '\b') /* backspace */
if (k) /* more than one char ? */
{
if (*(tmp + --k) == '$')
k--;
i++;
}
else
i++; /* no or just one char.. Skip backsp */
else
if (isascii(*(t->buf + i)) && isprint(*(t->buf + i)))
{
if ((*(tmp + k) = *(t->buf + i)) == '$')
*(tmp + ++k) = '$';
k++;
i++;
}
else
i++;
else {
*(tmp + k) = 0;
if(*tmp == '!')
strcpy(tmp,t->last_input);
else
strcpy(t->last_input,tmp);
write_to_q(tmp, &t->input);
if(t->snoop.snoop_by) {
write_to_q("% ",&t->snoop.snoop_by->desc->output);
write_to_q(tmp,&t->snoop.snoop_by->desc->output);
write_to_q("\n\r",&t->snoop.snoop_by->desc->output);
}
if (flag) {
out_char = t->character; /* SLUG_CHANGE 11-17-96 */
sprintf(buffer, "Line too long. Truncated to:\n\r%s\n\r", 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;
}
}
return(1);
}
void close_sockets(int s)
{
log("Closing all sockets.");
shutdown(s,2);
while(descriptor_list){
close_socket(descriptor_list);
}
close(s);
}
void close_socket(struct descriptor_data *d)
{
struct affected_type *af;
struct descriptor_data *tmp;
char buf[100];
close(d->descriptor);
flush_queues(d);
if (d->descriptor == maxdesc)
--maxdesc;
/* Forget snooping */
if (d->snoop.snooping)
d->snoop.snooping->desc->snoop.snoop_by = 0;
if (d->snoop.snoop_by) {
send_to_char("Your victim is no longer among us.\n\r",d->snoop.snoop_by);
d->snoop.snoop_by->desc->snoop.snooping = 0;
}
if (d->character){
if (d->connected == CON_PLYNG) {
save_char(d->character, NOWHERE);
stash_char(d->character,0);
act("$n has lost $s link.", TRUE, d->character, 0, 0, TO_ROOM);
sprintf(buf, "Closing link to: %s.", GET_NAME(d->character));
log(buf);
d->character->desc = 0;
} else {
/*
sprintf(buf, "Losing player: %s.", GET_NAME(d->character));
log(buf);
*/
free_char(d->character);
}
} else
/*
log("Losing descriptor without char.");
*/
if (next_to_process == d) /* to avoid crashing the process loop */
next_to_process = next_to_process->next;
if (d == descriptor_list) /* this is the head of the list */
descriptor_list = descriptor_list->next;
else /* This is somewhere inside the list */ {
/* Locate the previous element */
for (tmp = descriptor_list; (tmp->next != d) && tmp;
tmp = tmp->next);
tmp->next = d->next;
}
if (d->showstr_head)
free(d->showstr_head);
free(d);
}
void nonblock(int s)
{
#ifndef NO_FNDELAY
if (fcntl(s, F_SETFL, FNDELAY) == -1)
{
perror("Noblock");
exit(1);
}
#endif
}
/* ****************************************************************
* Public routines for system-to-player-communication *
**************************************************************** */
void send_to_char(char *messg, struct char_data *ch)
{
if(ch->desc && messg)
write_to_q(messg, &ch->desc->output);
}
void send_to_all(char *messg)
{
struct descriptor_data *i;
if (messg)
for (i = descriptor_list; i; i = i->next)
if (!i->connected)
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)
if (OUTSIDE(i->character))
write_to_q(messg, &i->output);
}
void send_to_except(char *messg, struct char_data *ch)
{
struct descriptor_data *i;
if (messg)
for (i = descriptor_list; i; i = i->next)
if (ch->desc != i && !i->connected)
write_to_q(messg, &i->output);
}
void send_to_room(char *messg, int room)
{
struct char_data *i;
if (messg)
for (i = world[room].people; i; i = i->next_in_room)
if (i->desc)
write_to_q(messg, &i->desc->output);
}
void send_to_room_except(char *messg, int room, struct char_data *ch)
{
struct char_data *i;
if (messg)
for (i = world[room].people; i; i = i->next_in_room)
if (i != ch && i->desc)
write_to_q(messg, &i->desc->output);
}
void send_to_room_except_two
(char *messg, int room, struct char_data *ch1, struct char_data *ch2)
{
struct char_data *i;
if (messg)
for (i = world[room].people; i; i = i->next_in_room)
if (i != ch1 && i != ch2 && i->desc)
write_to_q(messg, &i->desc->output);
}
/* higher-level communication */
void act(char *str, int hide_invisible, struct char_data *ch,
struct obj_data *obj, void *vict_obj, int type)
{
char *strp, *point, *i;
struct char_data *to;
char buf[MAX_STRING_LENGTH];
if (!str)
return;
if (!*str)
return;
if (type == TO_VICT)
to = (struct char_data *) vict_obj;
else if (type == TO_CHAR)
to = ch;
else
to = world[ch->in_room].people;
for (; to; to = to->next_in_room) {
if (to->desc && ((to != ch) || (type == TO_CHAR)) &&
(CAN_SEE(to, ch) || !hide_invisible) && 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); break;
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); break;
case 'p': i = OBJS(obj, to); break;
case 'P': i = OBJS((struct obj_data *) vict_obj, to); break;
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:
log("Illegal $-code to act():");
log(str);
break;
}
while (*point = *(i++))
++point;
++strp;
}
else if (!(*(point++) = *(strp++)))
break;
*(--point) = '\n';
*(++point) = '\r';
*(++point) = '\0';
if((type & 1) || !IS_SET(to->specials.act,PLR_VERYBRIEF))
write_to_q(CAP(buf), &to->desc->output);
}
if ((type == TO_VICT) || (type == TO_CHAR))
return;
}
}
void freaky(struct descriptor_data *d)
{
char buf[128];
struct char_data *vict;
int i;
vict=d->original ? d->original : d->character;
sprintf(buf,"Freaky: %d %d %s",
d->connected,
d->descriptor,
vict->player.name);
log(buf);
stash_char(vict,0);
for(i=0;i<MAX_WEAR;i++)
if(vict->equipment[i]){
extract_obj(unequip_char(vict,i));
vict->equipment[i]=0;
}
wipe_obj(vict->carrying);
vict->carrying=0;
if(vict->desc)
close_socket(vict->desc);
extract_char(vict);
}
void signal_setup(void)
{
struct itimerval itime;
struct timeval interval;
signal(SIGUSR2, shutdown_request);
signal(SIGALRM, logsig);
/*siginterrupt(SIGHUP , 1); */ signal(SIGHUP , hupsig);
/*siginterrupt(SIGINT , 1); */ signal(SIGINT , hupsig);
/*siginterrupt(SIGTERM, 1); */ signal(SIGTERM, hupsig);
/*siginterrupt(SIGSEGV, 1); */ signal(SIGSEGV, hupsig);
/*siginterrupt(SIGBUS , 1); */ signal(SIGBUS , hupsig);
/*siginterrupt(SIGPIPE, 1); */ signal(SIGPIPE, hupsig);
/*siginterrupt(SIGTRAP, 1); */ signal(SIGTRAP, hupsig);
return;
interval.tv_sec = 900; /* 15 minutes */
interval.tv_usec = 0;
itime.it_interval = interval;
itime.it_value = interval;
setitimer(ITIMER_VIRTUAL, &itime, 0);
signal(SIGVTALRM, checkpointing);
}
void checkpointing(int sig)
{
extern int tics;
if (!tics) {
log("CHECKPOINT shutdown: tics not updated");
abort();
}
else
tics = 0;
log("checkpointing");
exit(0);
}
void shutdown_request(int sig)
{
send_to_all("Shut down signal has been received.\n\r");
log("Received USR2 - shutdown request");
shutdowngame = 1;
}
/* kick out players etc */
void hupsig(int sig)
{
char ss[MAX_STRING_LENGTH];
struct descriptor_data *tmp, *point;
signal(sig,hupsig);
sigct++;
sprintf(ss,"SIG(%d,%d): %s %s",
sigct,sig,xo->character->player.name,xo->host);
--GET_INT(xo->character);
log(ss);
if(sigct > 3)
exit(0);
if(sigct > 1)
shutdowngame = 100;
longjmp(env,sigct);
}
void logsig(int sig)
{
log("Signal received. Ignoring.");
}