/*********************************************************************/
/* file: main.c - main module - signal setup/shutdown etc */
/* TINTIN III */
/* (T)he K(I)cki(N) (T)ickin D(I)kumud Clie(N)t */
/* coded by peter unold 1992 */
/*********************************************************************/
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include "tintin.h"
#ifndef BADSIG
#define BADSIG (void (*)())-1
#endif
/*************** globals ******************/
int term_echoing=TRUE;
int echo=DEFAULT_ECHO;
int ignore=DEFAULT_IGNORE;
int speedwalk=DEFAULT_SPEEDWALK;
int sessionsstarted;
struct session *sessionlist, *activesession;
struct listnode *common_aliases, *common_actions, *common_subs;
char vars[10][BUFFER_SIZE]; /* the &0, &1, &2,....&9 variables */
char tintin_char=DEFAULT_TINTIN_CHAR;
/************ externs *************/
extern int ticker_interrupted, time0;
extern int tick_size, sec_to_tick;
extern int ignore;
/**************************************************************************/
/* main() - show title - setup signals - init lists - readcoms - tintin() */
/**************************************************************************/
main(int argc, char *argv[])
{
puts("##################################################");
puts("# T I N T I N #");
puts("# version III #");
puts("# (T)he k(I)cki(N) (T)ickin d(I)kumud clie(N)t #");
puts("# a DIKU-mud client coded by peter unold 1992. #");
puts("##################################################");
prompt(NULL);
if(signal(SIGTERM, myquitsig)==BADSIG)
syserr("signal SIGTERM");
if(signal(SIGINT, myquitsig)==BADSIG)
syserr("signal SIGINT");
if(signal(SIGALRM, tick_func)==BADSIG)
syserr("signal SIGALRM");
time0=time(NULL);
alarm(1);
common_aliases=init_list();
common_actions=init_list();
common_subs=init_list();
if(argv[1])
activesession=read_command(argv[1], NULL);
tintin();
}
/***************************/
/* the main loop of tintin */
/***************************/
void tintin()
{
char buffer[BUFFER_SIZE];
int didget;
int readfdmask;
struct session *sesptr;
while(TRUE) {
readfdmask=1;
for(sesptr=sessionlist; sesptr; sesptr=sesptr->next)
readfdmask|=sesptr->socketbit;
ticker_interrupted=FALSE;
if(select(32, &readfdmask, 0, 0, 0)<0 && !ticker_interrupted)
syserr("select");
if(ticker_interrupted)
ticker_interrupted=FALSE;
else {
if(readfdmask&1) {
if((didget=read(0, buffer, sizeof(buffer)))<0)
syserr("read from fd 0");
*(buffer+didget-1)='\0';
if(activesession && term_echoing)
do_history(buffer, activesession);
activesession=parse_input(buffer, activesession);
}
for(sesptr=sessionlist; sesptr; sesptr=sesptr->next)
if(sesptr->socketbit&readfdmask)
read_mud(sesptr);
}
}
}
/*************************************************************/
/* read text from mud and test for actions/snoop/substitutes */
/*************************************************************/
void read_mud(struct session *ses)
{
char buffer[BUFFER_SIZE], subresult[BUFFER_SIZE], linebuffer[BUFFER_SIZE], *cp, *cpsource, *cpdest;
int didget;
if(!(didget=read_buffer_mud(buffer, ses))) {
cleanup_session(ses);
if(ses==activesession)
activesession=newactive_session();
}
else {
if(ses->logfile)
fwrite(buffer, didget, 1, ses->logfile);
do_all_subs(buffer, subresult, ses);
if(ses==activesession)
write(1, subresult, strlen(subresult));
else if(ses->snoopstatus)
snoop(buffer, ses);
if(!ignore)
split_check_all_actions(buffer, ses);
}
}
/**********************************************************/
/* snoop session ses - chop up lines and put'em in buffer */
/**********************************************************/
void snoop(char *buffer, struct session *ses)
{
int n;
char *cpsource, *cpdest, linebuffer[BUFFER_SIZE];
putchar('\n');
cpsource=buffer;
cpdest=linebuffer;
while(*cpsource) { /*cut out each of the lines and sub'em if a sub is triggered*/
if(*cpsource=='\n' || *cpsource=='\r') {
*cpdest='\0';
if(*linebuffer!='\0')
printf("%s%% %s\n", ses->name, linebuffer);
if(*cpsource=='\n' || *cpsource=='\r')
cpsource++;
cpdest=linebuffer;
}
else
*cpdest++=*cpsource++;
}
*cpdest='\0';
if(*linebuffer!='\0')
printf("%s%% %s\n", ses->name, linebuffer);
}
/*****************************************************/
/* output to screen should go throught this function */
/* text gets checked for actions */
/*****************************************************/
void tintin_puts(char *cptr, struct session *ses)
{
if(ses==activesession || ses==NULL) {
printf("%s\n\r", cptr);
prompt(ses);
}
if(ses)
check_all_actions(cptr, ses);
}
/****************************************/
/* alarm signal handler used for ticker */
/****************************************/
static void tick_func()
{
ticker_interrupted=TRUE;
alarm(1);
if(signal(SIGALRM, tick_func)==BADSIG)
syserr("signal SIGALRM");
sec_to_tick=tick_size-((time(NULL)-time0)%tick_size);
if(sec_to_tick==tick_size || sec_to_tick==10) {
struct session *sesptr;
for(sesptr=sessionlist; sesptr; sesptr=sesptr->next)
if(sesptr->tickstatus)
if(sec_to_tick==tick_size)
tintin_puts("#TICK!!!", sesptr);
else
tintin_puts("#10 SECONDS TO TICK!!!", sesptr);
}
}
/**********************************************************/
/* Here's where we go when we wanna quit TINTIN FAAAAAAST */
/**********************************************************/
static void myquitsig()
{
struct session *sesptr;
for(sesptr=sessionlist; sesptr; sesptr=sesptr->next)
cleanup_session(sesptr);
puts("\n\rYour fireball hits TINTIN with full force, causing an immediate death.");
puts("TINTIN is dead! R.I.P.");
puts("Your blood freezes as you hear TINTIN's death cry.");
exit(0);
}