From: blackman@acsu.buffalo.edu (Cancholech)
Newsgroups: rec.games.mud
Subject: TINTIN with TICKSHOUT AND TICKYELL...
Date: 10 Apr 92 16:34:54 GMT
Organization: UB

Ok so i did a little fixing of tintin on my own and well
here it is.....

hope you dont mind peter

It includes TICKSHOUT AND TICKYELL so now you can be really 
annoying if you want.




/*                 T I N T I N v1.0
 *     (T)he K(I)cki(N) (T)ick D(I)kumud Clie(N)t
 *             Coded by Peter Unold 1992
 *            email: pjunold@daimi.aau.dk
 */
#include <stdio.h>
#include <string.h> 
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <ctype.h>

#define ALIASROOM 30
#define ACTIONROOM 30

/******** PROTOTYPES FOR FUNCTIONS **********/
void runtintin(void);
void syserr(char *msg);
void read_coms(char *filename);
void parseinput(char *command, char *arg);
void infofd(int fd);
void tickon();
void tickoff();
void getuserinput();
static void tickfunc();
static void myquitsig();
void parse_input(char *command);
void parse_tintin(char *command, char *arg);
void substitute_alias(char *cpsource, char *cpdest, char *cpsubtext);
int search_alias(char *cptr);
char *space_out(char *cptr);
void check_action();
void gettelnetoutput();
void parse_alias(char *cptr);
void parse_action(char *cptr);
void show_aliases();
void show_actions();

char inputline[50];

char aliasleft[ALIASROOM][20];
char aliasright[ALIASROOM][100];
int aliasno=0;

char actionleft[ACTIONROOM][100];
char actionright[ACTIONROOM][100];
int actionno=0;

int pfdto[2],pfdfrom[2];

char buffer[512], linebuffer[512];
char *cpbufferdest=linebuffer;
char *netaddress, *portnumber;

long time0;
int sec_to_tick,tickswitch=0;

int main(int argc, char *argv[])
{
  if(argc!=3) {
    fprintf(stderr,"USAGE: tintin mudaddress portnumber\n");
    exit(1);
  }

  netaddress=argv[1];
  portnumber=argv[2];
  runtintin();  

  return(0);
}

/**********************************/
/* child process - calling telnet */
/**********************************/
mychild()
{
  if(close(1)==-1)
    syserr("close0");
  if(dup(pfdfrom[1])!=1)
    syserr("dup");
  if(close(pfdfrom[0])==-1 || close(pfdfrom[1])==-1)
    syserr("close");
  if(close(0)==-1)
    syserr("close1");
  if(dup(pfdto[0])!=0)
    syserr("dup");
  if(close(pfdto[0])==-1 || close(pfdto[1])==-1)
    syserr("close2");
  execlp("telnet","telnet",netaddress,portnumber,NULL);
  syserr("execl");
}

/**********************************************************/
/* main function. stays in it until a signal get's it out */
/**********************************************************/
void runtintin(void)
{
  int i,flag,inputlinelen,dun=0;
  char inputline[80],*argptr,linebuffer[512];
  char *cptr,*cptrs,*cptrd;

  if(pipe(pfdto)==-1)
    syserr("pipe");
  if(pipe(pfdfrom)==-1)
    syserr("pipe"); 

  switch(fork()) {
    case -1:
      syserr("fork");
    case 0:
      mychild();
      break;
  }

   if(close(pfdto[0])==-1)
     syserr("close");
   if(close(pfdfrom[1])==-1)
     syserr("close"); 

  if(signal(SIGCLD,myquitsig)==BADSIG)
    syserr("signal");
  if(signal(SIGINT,myquitsig)==BADSIG)
    syserr("signal");
  if(signal(SIGTERM,myquitsig)==BADSIG)
    syserr("signal");
  if(signal(SIGPIPE,myquitsig)==BADSIG)
    syserr("signal");

/****************MAIN-LOOP***************************/

  cptrd=linebuffer;
  puts("Thank you for using TINTIN. The first C written Dikuclient\n");

  for(;;) {

    gettelnetoutput();

    if(dun==0) {                  /*make pipes none-buffered, only done once */
      flag=fcntl(0,F_GETFL ,0);   /*this is weird, but it MUST be right here*/
      fcntl(0,F_SETFL,flag | O_NDELAY); 
      flag=fcntl(pfdfrom[0],F_GETFL ,0);
      fcntl(pfdfrom[0],F_SETFL,flag | O_NDELAY); 
      dun=1;
    }

    getuserinput();
  }

}

/**********************************************/
/* GET OUTPUT FROM TELNET AND CUT INTO LINES  */
/**********************************************/
void gettelnetoutput()
{
  char *cpbuffersource;
  int chargot;

  if((chargot=read(pfdfrom[0],buffer,512))>0) {
    write(1,buffer,chargot);

    cpbuffersource=buffer;

    while(cpbuffersource<buffer+chargot) {
      if(*cpbuffersource=='\n') {
        *cpbufferdest='\0';
        cpbufferdest=linebuffer;
        cpbuffersource++;
        check_action();
      }
      else
        *cpbufferdest++=*cpbuffersource++;
    }
  }
}

/***********************/
/* check for an action */
/***********************/
void check_action()
{
  int i;
  char *cp, outtext[512];

  i=-1;
  while(++i<actionno) {
    if(actionleft[i][0]=='&' && (cp=strchr(linebuffer+1,' '))!=NULL &&
    stricmp(&actionleft[i][2], cp+1)==NULL) {
      *cp='\0';
      substitute_alias(actionright[i], outtext, linebuffer+1 );      
      parse_input(outtext);
      break;
    }
    else if(stricmp(&actionleft[i][0], linebuffer+1)==NULL) {
      printf("[%s]\n",actionright[i]);
      parse_input(actionright[i]);
    }
  }
}

/**************************************/
/* READ USER INPUT AND SEND TO PARSER */
/**************************************/
void getuserinput()
{
  char inputline[512];
  int inputlinelen;

  inputlinelen=read(0, inputline, 80);
  if(inputlinelen>=0) { 
    inputline[inputlinelen-1]='\0';
    parse_input(inputline);
  }
}

/********************************/
/* SEND A TEXT-STRING TO TELNET */
/********************************/
void sendtotelnet(char *cptr)
{
  char textout[512];
  int i;

  strcpy(textout, cptr);
  textout[i=strlen(cptr)]='\n';
  if(write(pfdto[1], textout, i+1)==-1)
    syserr("write");
}

/****************************/
/* SUB-ROUNTINES FOR TICKER */
/****************************/
void tickon()
{
  tickswitch=1;
  time0=time(NULL);
  if(signal(SIGALRM,tickfunc)==BADSIG)
    syserr("signal");
  alarm(1);
  printf("#Ticker has been reset and is now running\n");
}

void tickoff()
{
  tickswitch=0;
  printf("#Ticker is now off\n");
}

static void tickfunc()
{
  if(tickswitch) {
    alarm(1);
    sec_to_tick=75-((time(NULL)-time0)%75);
    if(sec_to_tick==10)
      printf("#10 seconds left in this tick\n");
    else if(sec_to_tick==5)
      printf("#5 seconds left in this tick\n");
  }
}

/*********************************************/
/* this is where we get out when telnet dies */
/*********************************************/
static void myquitsig()
{
  int flag;

  flag=fcntl(0,F_GETFL ,0);
  fcntl(0,F_SETFL,flag & ~O_NDELAY); 
  printf("\n#Very nice job. Hope you had fun\n");
  exit(0);
}
 
/*************************************************/
/* print system call error message and terminate */
/* this function was lifted... SO WHAT!?!?!??!   */
/*************************************************/
void syserr(char *msg)
{
  extern int errno, sys_nerr;
  extern char *sys_errlist[];

  fprintf(stderr,"ERROR: %s (%d",msg, errno);
  if(errno>0 && errno<sys_nerr)
    fprintf(stderr,": %s)\n",sys_errlist[errno]);
  else
    fprintf(stderr,")\n");
  exit(1);
}

/************************************/
/* READ AND PARSE ALIAS/ACTION FILE */
/************************************/
void read_coms(char *filename)
{
  FILE *myfile;
  char inputline[100],*cptr;
  int aliaslen,actionlen;

  if((myfile=fopen(filename,"rt"))==NULL) {
    printf("#ERROR - couldn't open file:%s\n ",filename);
    return;
  }

  while(fgets(inputline, 100, myfile)) {
    *(strchr(inputline, '\n'))='\0';
    if(strncmp(inputline, "#alias ", 7)==NULL) 
      parse_alias(inputline+7);
    if(strncmp(inputline, "#action ", 8)==NULL) 
      parse_action(inputline+8);
  }

  fclose(myfile);
}

/********************************************************/
/* Parse input from user and write to telnet input pipe */
/********************************************************/
void parse_input(char *commandline)
{
  int aliascomno;

  char command[512], arg[512], outtext[512];
  char *cpsource, *cpdest;

  if(*commandline=='\0')
    sendtotelnet(commandline);    

  cpsource=commandline;

  while(*cpsource!='\0') {

    cpsource=space_out(cpsource);
    cpdest=command;

    while(*cpsource!=';' && *cpsource!=' ' && *cpsource!='\0')
      *cpdest++=*cpsource++;
    *cpdest='\0';

    cpsource=space_out(cpsource);
    cpdest=arg;

    while(*cpsource!=';' && *cpsource!='\0')
      *cpdest++=*cpsource++;
    *cpdest='\0';

    aliascomno=search_alias(command);
    if(aliascomno<aliasno) {
      substitute_alias(aliasright[aliascomno], command, arg);
      parse_input(command);
    }
    else {
      if(*command=='#')      
        parse_tintin(command,arg);
      else {
        if(*arg!='\0') {
          strcat(command, " ");
          strcat(command, arg);
        }
        sendtotelnet(command);
      }
    }

    if(*cpsource==';')
      cpsource++;
  }

}

/**********************************************/
/* Parse Tintin's special commands            */
/* this is where to stuff in your own comands */
/**********************************************/
void parse_tintin(char *command, char *arg)
{
  char outtext[100];
  int i;

/*********REPEAT COMMAND*********/
  if(isdigit(*(command+1))) {
    i=atoi(command+1);
    if(i>0 && i<21) {
      while(i-->0)
        parse_input(arg);
    }
    else
      printf("#Only values between 1 and 20 are acceptable\n ");
  return;
  }

/**********TICKON COMMAND**********/
  if(stricmp("#tickon",command)==0) {
    tickon();
    return;
  }

/**********TICKOFF COMMAND**********/
  if(stricmp("#tickoff",command)==0) {
    tickoff();
    return;
  }

/**********TICK COMMAND**********/
  if(stricmp("#tick",command)==0) {
    if(tickswitch)
      printf("#%d seconds left\n",sec_to_tick);
    else
      printf("#The Ticktimer is not running\n");
    return;
  }

/**********TICKTELL COMMAND**********/
  if(stricmp("#ticktell",command)==0 && *arg!='\0') {
    sprintf(outtext,"tell %s there are now %d seconds left in this tick.",arg,sec_to_tick);
    parse_input(outtext);  
    return;
  }

/***********TICKSHOUT COMMAND**********/
  if(stricmp("#tickshout",command)==0) {
    sprintf(outtext,"shout there are now '%d' seconds left in this tick",sec_to_tick);
    parse_input(outtext);  
    return;
  }

/***********TICKYELL COMMAND**********/
  if(stricmp("#tickyell",command)==0) {
    sprintf(outtext,"yell there are now '%d' seconds left in this tick",sec_to_tick);
    parse_input(outtext);  
    return;
  }

/**********ALIAS COMMAND**********/
  if(stricmp("#alias",command)==0) {
    if(*arg=='\0')
      show_aliases();
    else
      parse_alias(arg);
    return;
  }

/**********ACTION COMMAND**********/
  if(stricmp("#action",command)==0) {
    if(*arg=='\0')
      show_actions();
    else
      parse_action(arg);
    return;
  }

/**********READCOMS**************/
  if(stricmp("#readcoms",command)==0) {
    if(*arg=='\0')
      printf("#Load which file?\n ");
    else
      read_coms(arg);
    return;
   }

/************HELP************/
  if(stricmp("#help",command)==0) {
    printf("#List of TINTIN commands:\n ");
 printf("#number command             :repeats 'command' 'number' of times\n ");
 printf("#action [prompt=command]    :list/delete/display/define actions\n ");
 printf("#alias  [alias=command]     :list/delete/display/define aliases\n ");
 printf("#help                       :this page\n ");
 printf("#readcoms <filename>        :readin file with action/alias defs.\n ");
 printf("#tickon                     :toggles tick-clock/warnings ON\n ");
 printf("#tickoff                    :toggles tick-clock/warnings OFF\n ");
 printf("#tick                       :displays # of seconds til next tick\n ");
 printf("#tickshout                  :shout how many seconds left\n ");
 printf("#tickyell                   :Yell how many seconds left\n ");
 printf("#ticktell player            :tell 'player' how many seconds left\n ");
    return;
  }

  printf("#That is an UNDEFINED command\n ");
}

/**************************************/
/* Substitute all '&'s with cpsubtext */
/**************************************/
void substitute_alias(char *cpsource, char *cpdest, char *cpsubtext)
{
  int subtextlen=strlen(cpsubtext);

  while(*cpsource) {
    if(*cpsource=='&') {
      if(*cpsubtext=='\0') {
        *cpdest++=' ';
        cpsource++;
      }
      else {
        strcpy(cpdest, cpsubtext);
        cpdest+=subtextlen;
        cpsource++;
      }
    }
    else
      *cpdest++=*cpsource++;
  }
  *cpdest='\0';
}

/*********************************************/
/* search for alias in list                  */ 
/* return alias index or aliasno if notfound */
/*********************************************/
int search_alias(char *cptr)
{
  int i=-1;
  while(++i<aliasno && stricmp(aliasleft[i], cptr));
  return i;
}

/***********************************************/
/* search for action in list                   */ 
/* return action index or actionno if notfound */
/***********************************************/
int search_action(char *cptr)
{
  int i=-1;
  while(++i<actionno && stricmp(actionleft[i], cptr));
  return i;
}

/**************************************/
/* move pointer to next no-space-char */
/**************************************/
char *space_out(char *cptr)
{
  while(*cptr==' ')
    cptr++;
  return cptr;
}

/***********************************/
/* PARSE AN ALIAS. ADD/DELETE/SHOW */
/***********************************/
void parse_alias(char *cptr)
{
  int i,j;
  char *left,*right,*cptr2;

  left=cptr=space_out(cptr);

  while(*cptr!='=' && *cptr!=' ' && *cptr!='\0')
    cptr++;

  cptr2=strchr(cptr, '=');

  *cptr='\0';

  if(cptr2==NULL) {
    if((i=search_alias(left))<aliasno)
      printf("#Alias: %s=%s\n ",aliasleft[i],aliasright[i]);
    else
      printf("#Unknown alias:%s\n ",left);
  }

  else {
    right=cptr=space_out(++cptr2);
    if(*right!='\0') {
      if((i=search_alias(left))==aliasno)
	aliasno++;
      strcpy(aliasleft[i], left);
      strcpy(aliasright[i], right);
      printf("#New Alias:%s=%s\n ",left,right);
    }

    else {
      if((i=search_alias(left))==aliasno)
	printf("#Unknown alias:%s\n ",left);
      else {
	j=i;
	while(j<aliasno) {
	  strcpy(aliasleft[i],aliasleft[j]);
	  strcpy(aliasright[i],aliasright[j]);
	  j++;
	}
	aliasno--;
	printf("#Alias DELETED\n ");
      }
    }
  }
}

/************************************/
/* PARSE AN ACTION. ADD/DELETE/SHOW */
/************************************/
void parse_action(char *cptr)
{
  int i,j;
  char *left,*right,*cptr2;

  left=cptr=space_out(cptr);

  while(*cptr!='=' && *cptr!='\0')
    cptr++;

  cptr2=strchr(cptr, '=');

  *cptr='\0';

  if(cptr2==NULL) {
    if((i=search_action(left))<actionno)
      printf("#Action: %s=%s\n ",actionleft[i],actionright[i]);
    else
      printf("#Unknown action:%s\n ",left);
  }

  else {
    right=cptr=space_out(++cptr2);
    if(*right!='\0') {
      if((i=search_action(left))==actionno)
	actionno++;
      strcpy(actionleft[i], left);
      strcpy(actionright[i], right);
      printf("#New Action:%s=%s\n ",left,right);
    }

    else {
      if((i=search_action(left))==actionno)
	printf("#Unknown Action:%s\n ",left);
      else {
	j=i;
	while(j<actionno) {
	  strcpy(actionleft[i],actionleft[j]);
	  strcpy(actionright[i],actionright[j]);
	  j++;
	}
	actionno--;
	printf("#Action DELETED\n ");
      }
    }
  }
}


/****************/
/* list aliases */
/****************/
void show_aliases()
{
  int i=0;
  printf("#This many aliases have been defined= %d \n ",aliasno);

  while(i<aliasno) {
    printf("#Alias: %s=%s\n ",aliasleft[i],aliasright[i]);
    i++;
  }
}

/****************/
/* list actions */
/****************/
void show_actions()
{
  int i=0;
  printf("#You have defined %d actions.\n ",actionno);

  while(i<actionno) {
    printf("#Action: %s=%s\n ",actionleft[i],actionright[i]);
    i++;
  }
}

-- 
My newest favourite oxymoron:
			(The) Great American Beer (Festival)
What do American Beer and Sex-in-a-Canoe have in common??????????????
rutgers!ub!blackman blackman@acsu.buffalo.edu