|  | @@ -19,6 +19,36 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <regex.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* Log level guideline:
 | 
	
		
			
				|  |  | + * - ZF_LOG_FATAL - happened something impossible and absolutely unexpected.
 | 
	
		
			
				|  |  | + *   Process can't continue and must be terminated.
 | 
	
		
			
				|  |  | + *   Example: division by zero, unexpected modifications from other thread.
 | 
	
		
			
				|  |  | + * - ZF_LOG_ERROR - happened something possible, but highly unexpected. The
 | 
	
		
			
				|  |  | + *   process is able to recover and continue execution.
 | 
	
		
			
				|  |  | + *   Example: out of memory (could also be FATAL if not handled properly).
 | 
	
		
			
				|  |  | + * - ZF_LOG_WARN - happened something that *usually* should not happen and
 | 
	
		
			
				|  |  | + *   significantly changes application behavior for some period of time.
 | 
	
		
			
				|  |  | + *   Example: configuration file not found, auth error.
 | 
	
		
			
				|  |  | + * - ZF_LOG_INFO - happened significant life cycle event or major state
 | 
	
		
			
				|  |  | + *   transition.
 | 
	
		
			
				|  |  | + *   Example: app started, user logged in.
 | 
	
		
			
				|  |  | + * - ZF_LOG_DEBUG - minimal set of events that could help to reconstruct the
 | 
	
		
			
				|  |  | + *   execution path. Usually disabled in release builds.
 | 
	
		
			
				|  |  | + * - ZF_LOG_VERBOSE - all other events. Usually disabled in release builds.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * *Ideally*, log file of debugged, well tested, production ready application
 | 
	
		
			
				|  |  | + * should be empty or very small. Choosing a right log level is as important as
 | 
	
		
			
				|  |  | + * providing short and self descriptive log message.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | +#define ZF_LOG_VERBOSE 1
 | 
	
		
			
				|  |  | +#define ZF_LOG_DEBUG   2
 | 
	
		
			
				|  |  | +#define ZF_LOG_INFO    3
 | 
	
		
			
				|  |  | +#define ZF_LOG_WARN    4
 | 
	
		
			
				|  |  | +#define ZF_LOG_ERROR   5
 | 
	
		
			
				|  |  | +#define ZF_LOG_FATAL   6
 | 
	
		
			
				|  |  | +*/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // LOGGING with file output
 | 
	
		
			
				|  |  |  #include "zf_log.h"
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -43,29 +73,6 @@ static void file_output_open(const char *const log_path) {
 | 
	
		
			
				|  |  |    zf_log_set_output_v(ZF_LOG_PUT_STD, 0, file_output_callback);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// END LOGGING
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#include "lastseen.h"
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// http://c-faq.com/lib/randrange.html
 | 
	
		
			
				|  |  | -int randint(int N) { return rand() / (RAND_MAX / N + 1); }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// http://c-faq.com/lib/randrange.html
 | 
	
		
			
				|  |  | -// numbers in the range [M, N] could be generated with something like
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -int randrange(int M, int N) {
 | 
	
		
			
				|  |  | -  return M + rand() / (RAND_MAX / (N - M + 1) + 1);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/*
 | 
	
		
			
				|  |  | -What is the name of the actual, real Mystic executable
 | 
	
		
			
				|  |  | -that we'll be executing and mangling?
 | 
	
		
			
				|  |  | -*/
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#define TARGET "./mySTIC"
 | 
	
		
			
				|  |  | -// Size of our input and output buffers.
 | 
	
		
			
				|  |  | -#define BSIZE 128
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * Display a repr of the given string.
 | 
	
		
			
				|  |  |   *
 | 
	
	
		
			
				|  | @@ -143,6 +150,62 @@ const char *repr(const char *data) {
 | 
	
		
			
				|  |  |    return buffer;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#define CHUNKSIZE 32
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void zf_repr_chunk(int LOG_LEVEL, const char *chunk) {
 | 
	
		
			
				|  |  | +  const char *output = repr(chunk);
 | 
	
		
			
				|  |  | +  ZF_LOG_WRITE(LOG_LEVEL, _ZF_LOG_TAG, "r\"%s\"", output);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void zf_repr(int LOG_LEVEL, const char *string) {
 | 
	
		
			
				|  |  | +  // Chunks -- 32?
 | 
	
		
			
				|  |  | +  char buffer[CHUNKSIZE + 1];
 | 
	
		
			
				|  |  | +  int pos = 0;
 | 
	
		
			
				|  |  | +  int len = strlen(string);
 | 
	
		
			
				|  |  | +  while (len > CHUNKSIZE) {
 | 
	
		
			
				|  |  | +    strncpy(buffer, string + pos, CHUNKSIZE);
 | 
	
		
			
				|  |  | +    buffer[CHUNKSIZE] = 0;
 | 
	
		
			
				|  |  | +    pos += CHUNKSIZE;
 | 
	
		
			
				|  |  | +    len -= CHUNKSIZE;
 | 
	
		
			
				|  |  | +    zf_repr_chunk(LOG_LEVEL, buffer);
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  if (len > 0) {
 | 
	
		
			
				|  |  | +    strcpy(buffer, string + pos);
 | 
	
		
			
				|  |  | +    zf_repr_chunk(LOG_LEVEL, buffer);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// Here's my idea for debugging
 | 
	
		
			
				|  |  | +#define ZF_LOGV_REPR(str) zf_repr(ZF_LOG_VERBOSE, str)
 | 
	
		
			
				|  |  | +#define ZF_LOGD_REPR(str) zf_repr(ZF_LOG_DEBUG, str)
 | 
	
		
			
				|  |  | +#define ZF_LOGI_REPR(str) zf_repr(ZF_LOG_INFO, str)
 | 
	
		
			
				|  |  | +#define ZF_LOGW_REPR(str) zf_repr(ZF_LOG_WARN, str)
 | 
	
		
			
				|  |  | +#define ZF_LOGE_REPR(str) zf_repr(ZF_LOG_ERROR, str)
 | 
	
		
			
				|  |  | +#define ZF_LOGF_REPR(str) zf_repr(ZF_LOG_FATAL, str)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// END LOGGING
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "lastseen.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// http://c-faq.com/lib/randrange.html
 | 
	
		
			
				|  |  | +int randint(int N) { return rand() / (RAND_MAX / N + 1); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// http://c-faq.com/lib/randrange.html
 | 
	
		
			
				|  |  | +// numbers in the range [M, N] could be generated with something like
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int randrange(int M, int N) {
 | 
	
		
			
				|  |  | +  return M + rand() / (RAND_MAX / (N - M + 1) + 1);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | +What is the name of the actual, real Mystic executable
 | 
	
		
			
				|  |  | +that we'll be executing and mangling?
 | 
	
		
			
				|  |  | +*/
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#define TARGET "./mySTIC"
 | 
	
		
			
				|  |  | +// Size of our input and output buffers.
 | 
	
		
			
				|  |  | +#define BSIZE 128
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |   * string_insert()
 | 
	
		
			
				|  |  |   * Inserts a string into a given position.
 | 
	
	
		
			
				|  | @@ -230,7 +293,7 @@ void console_init(struct console_details *cdp) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void ansi_color(struct console_details *cdp, int color) {
 | 
	
		
			
				|  |  | -  ZF_LOGV("ansi_color(%d)", color);
 | 
	
		
			
				|  |  | +  // ZF_LOGV("ansi_color(%d)", color);
 | 
	
		
			
				|  |  |    if (color == 0) {
 | 
	
		
			
				|  |  |      cdp->status = 0;
 | 
	
		
			
				|  |  |      cdp->fgcolor = 7;
 | 
	
	
		
			
				|  | @@ -679,6 +742,24 @@ void write_color(int fd, int color) {
 | 
	
		
			
				|  |  |    write(fd, buffer, strlen(buffer));
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +int send_file(int fd, char *filename) {
 | 
	
		
			
				|  |  | +  FILE *fp;
 | 
	
		
			
				|  |  | +  char buffer[100];
 | 
	
		
			
				|  |  | +  int read;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  fp = fopen(filename, "rb");
 | 
	
		
			
				|  |  | +  if (fp == NULL) {
 | 
	
		
			
				|  |  | +    ZF_LOGD("Failed to open %s", filename);
 | 
	
		
			
				|  |  | +    return 0;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  while ((read = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
 | 
	
		
			
				|  |  | +    write(fd, buffer, read);
 | 
	
		
			
				|  |  | +  };
 | 
	
		
			
				|  |  | +  fclose(fp);
 | 
	
		
			
				|  |  | +  return 1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * process_trigger( fd, *cp )
 | 
	
		
			
				|  |  |   *
 | 
	
	
		
			
				|  | @@ -716,7 +797,7 @@ const char *process_trigger(int fd, const char *cp) {
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |      break;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  case 'C':
 | 
	
		
			
				|  |  | +  case 'C': {
 | 
	
		
			
				|  |  |      i = 0;
 | 
	
		
			
				|  |  |      if (*cp == 'R') {
 | 
	
		
			
				|  |  |        cp++;
 | 
	
	
		
			
				|  | @@ -734,9 +815,25 @@ const char *process_trigger(int fd, const char *cp) {
 | 
	
		
			
				|  |  |        cp++;
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |      write_color(fd, i);
 | 
	
		
			
				|  |  | -    break;
 | 
	
		
			
				|  |  | +  } break;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  case 'F': {
 | 
	
		
			
				|  |  | +    // Ok, look for filename
 | 
	
		
			
				|  |  | +    char ansifile[32] = "./hh/";
 | 
	
		
			
				|  |  | +    char *ap = ansifile + strlen(ansifile);
 | 
	
		
			
				|  |  | +    while (*cp != '.') {
 | 
	
		
			
				|  |  | +      *ap = *cp;
 | 
	
		
			
				|  |  | +      ap++;
 | 
	
		
			
				|  |  | +      *ap = 0;
 | 
	
		
			
				|  |  | +      cp++;
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    strcat(ansifile, ".ans");
 | 
	
		
			
				|  |  | +    cp++;
 | 
	
		
			
				|  |  | +    ZF_LOGD("FILE [%s]", ansifile);
 | 
	
		
			
				|  |  | +    send_file(fd, ansifile);
 | 
	
		
			
				|  |  | +  } break;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  case 'G':
 | 
	
		
			
				|  |  | +  case 'G': {
 | 
	
		
			
				|  |  |      x = 0;
 | 
	
		
			
				|  |  |      if (isdigit(*cp)) {
 | 
	
		
			
				|  |  |        x = (*cp) - '0';
 | 
	
	
		
			
				|  | @@ -761,9 +858,9 @@ const char *process_trigger(int fd, const char *cp) {
 | 
	
		
			
				|  |  |      ZF_LOGD("GOTO (%d,%d)", x, y);
 | 
	
		
			
				|  |  |      sprintf(buffer, "\x1b[%d;%dH", y, x);
 | 
	
		
			
				|  |  |      write(fd, buffer, strlen(buffer));
 | 
	
		
			
				|  |  | -    break;
 | 
	
		
			
				|  |  | +  } break;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  case 'R':
 | 
	
		
			
				|  |  | +  case 'R': {
 | 
	
		
			
				|  |  |      i = 0;
 | 
	
		
			
				|  |  |      if (isdigit(*cp)) {
 | 
	
		
			
				|  |  |        i = (*cp) - '0';
 | 
	
	
		
			
				|  | @@ -775,8 +872,8 @@ const char *process_trigger(int fd, const char *cp) {
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |        current_render.effect = 0;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    break;
 | 
	
		
			
				|  |  | -  case 'S':
 | 
	
		
			
				|  |  | +  } break;
 | 
	
		
			
				|  |  | +  case 'S': {
 | 
	
		
			
				|  |  |      i = 0;
 | 
	
		
			
				|  |  |      if (isdigit(*cp)) {
 | 
	
		
			
				|  |  |        i = (*cp) - '0';
 | 
	
	
		
			
				|  | @@ -788,8 +885,8 @@ const char *process_trigger(int fd, const char *cp) {
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |        current_render.speed = 0;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    break;
 | 
	
		
			
				|  |  | -  case 'P':
 | 
	
		
			
				|  |  | +  } break;
 | 
	
		
			
				|  |  | +  case 'P': {
 | 
	
		
			
				|  |  |      i = 0;
 | 
	
		
			
				|  |  |      if (isdigit(*cp)) {
 | 
	
		
			
				|  |  |        i = (*cp) - '0';
 | 
	
	
		
			
				|  | @@ -802,7 +899,7 @@ const char *process_trigger(int fd, const char *cp) {
 | 
	
		
			
				|  |  |          sleep(i);
 | 
	
		
			
				|  |  |        };
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    break;
 | 
	
		
			
				|  |  | +  } break;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return cp;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -910,51 +1007,6 @@ void render(int fd, const char *string_out) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -// Beanzilla's no repeats
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#ifdef NOPE
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * have_seen( list, len, item )
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * Returns 1 (true) if item is in the list.
 | 
	
		
			
				|  |  | - * Rotates the list [x] = [x+1], and
 | 
	
		
			
				|  |  | - * list[len-1] = item, return 0 (false)
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -int have_seen(int *list, int len, int item) {
 | 
	
		
			
				|  |  | -  int x;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  for (x = 0; x < len; x++) {
 | 
	
		
			
				|  |  | -    if (list[x] == item) {
 | 
	
		
			
				|  |  | -      return 1;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Ok, it is something different
 | 
	
		
			
				|  |  | -  for (x = 0; x < len - 1; x++) {
 | 
	
		
			
				|  |  | -    list[x] = list[x + 1];
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | -  list[x] = item;
 | 
	
		
			
				|  |  | -  return 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * init_have_seen( list, len )
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * Initialize the have_seen list with -1.
 | 
	
		
			
				|  |  | - * (-1 isn't a valid index, so we start
 | 
	
		
			
				|  |  | - * out with all invalid.)
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -void init_have_seen(int *list, int len) {
 | 
	
		
			
				|  |  | -  int x;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  for (x = 0; x < len; x++) {
 | 
	
		
			
				|  |  | -    list[x] = -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |      These are harry "timeout" events.
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -962,8 +1014,6 @@ void init_have_seen(int *list, int len) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -LastSeen last_seen_harry_event(2);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  #ifdef CPP_MADMAN_STL_CODE
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const char *random_phrase(const char *words, int len, int last_seen) {
 | 
	
	
		
			
				|  | @@ -993,6 +1043,7 @@ void harry_idle_event(int fd) {
 | 
	
		
			
				|  |  |                             "MeOW",      "I see U",          "Arrooo!",
 | 
	
		
			
				|  |  |                             "Ahh-wooo!", "Aaaooo!"};
 | 
	
		
			
				|  |  |    const char *cp;
 | 
	
		
			
				|  |  | +  static LastSeen last_seen_harry_event(2);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Remember the last phrase used,
 | 
	
		
			
				|  |  |    // and don't repeat (the last two)!
 | 
	
	
		
			
				|  | @@ -1305,6 +1356,8 @@ int mangle(int fd, char *buffer) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Use terminal - clean out ANSI
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  ZF_LOGI("mangle:");
 | 
	
		
			
				|  |  | +  ZF_LOGI_REPR(buffer);
 | 
	
		
			
				|  |  |    ZF_LOGI("mangle(%s)", repr(buffer));
 | 
	
		
			
				|  |  |    // strcpy(work, buffer);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1332,13 +1385,8 @@ int mangle(int fd, char *buffer) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Don't activate on the very first CLS.  Too soon, don't screw up the ANSI
 | 
	
		
			
				|  |  |      // detection.
 | 
	
		
			
				|  |  | -    if ((ANSI_CLS_count > 1) && (random_activate(4))) {
 | 
	
		
			
				|  |  | -      int r;
 | 
	
		
			
				|  |  | -      char display[100] = "";
 | 
	
		
			
				|  |  | -      const char *phrasing[] = {"^R1Haha^P1ha^P1ha", "Poof!", "Got U",
 | 
	
		
			
				|  |  | -                                "Anyone there?", "^R1Knock, ^P1Knock"};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // import magic
 | 
	
		
			
				|  |  | +    if (ANSI_CLS_count > 1) {
 | 
	
		
			
				|  |  | +      // Ok, figure out the restore color, just in case
 | 
	
		
			
				|  |  |        struct console_details temp_console;
 | 
	
		
			
				|  |  |        // Make exact copy of our current console state.
 | 
	
		
			
				|  |  |        memcpy(&temp_console, &console, sizeof(console));
 | 
	
	
		
			
				|  | @@ -1347,61 +1395,137 @@ int mangle(int fd, char *buffer) {
 | 
	
		
			
				|  |  |        char restore_color[30]; // ansi color
 | 
	
		
			
				|  |  |        strcpy(restore_color, color_restore(&temp_console));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      ZF_LOGI("mangle(ANSI_CLS)");
 | 
	
		
			
				|  |  | -      // sprintf( display, "^P2...");
 | 
	
		
			
				|  |  | -      // This string actually screws up ANSI detection (takes too long)
 | 
	
		
			
				|  |  | -      // strcpy(display, "^P2^S501234567890^P1abcdef^P2g^P3h^P4i^S0^P2");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // strcpy(display, "^P2^S301234^P15^S0^P2");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // Add in random text, plus color!
 | 
	
		
			
				|  |  | -      r = random() % ((sizeof(phrasing) / sizeof(char *)) - 1);
 | 
	
		
			
				|  |  | -      int color = random() % 15 + 1;
 | 
	
		
			
				|  |  | -      int x = random() % 30 + 1;
 | 
	
		
			
				|  |  | -      int y = random() % 15 + 1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      /*
 | 
	
		
			
				|  |  | -      Don't have it pause there before moving the cursor.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      Move the cursor, get the color changed, THEN pause.
 | 
	
		
			
				|  |  | -      Then act all crazy.
 | 
	
		
			
				|  |  | +      if (random_activate(3)) {
 | 
	
		
			
				|  |  | +        char display[100] = "";
 | 
	
		
			
				|  |  | +        int needs_cls = 0;
 | 
	
		
			
				|  |  | +        struct file_need {
 | 
	
		
			
				|  |  | +          const char *filename;
 | 
	
		
			
				|  |  | +          int cls;
 | 
	
		
			
				|  |  | +        } possibles[] = {
 | 
	
		
			
				|  |  | +            {"goofy_head", 1},
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                "bat",
 | 
	
		
			
				|  |  | +                1,
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            {"panther", 1},
 | 
	
		
			
				|  |  | +            {"wolf", 1}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //          bat.ans       creature.ans  goofy_head.ans  panther.ans
 | 
	
		
			
				|  |  | +            //          skull.ans
 | 
	
		
			
				|  |  | +            // blinkman.ans  dog.ans       guy.ans         skull2.ans   wolf.ans
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      NOTE:  Make sure if you use any ^R Render effects, turn them off before
 | 
	
		
			
				|  |  | -      trying to display the restore_color.  :P   ^R0
 | 
	
		
			
				|  |  | -      Also, make sure you re-home the cursor ^G0101 because that's where they
 | 
	
		
			
				|  |  | -      are expecting the cursor to be!  (At least it's how Mystic does it.)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      HOME, CLS, HOME, ...  Not sure what others do there.  We'll see.
 | 
	
		
			
				|  |  | -      */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      sprintf(display, "^G%02d%02d^S3^C%02d^P1%s^S0^R0%s^P1^G0101", x, y, color,
 | 
	
		
			
				|  |  | -              phrasing[r], restore_color);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // sprintf(display, "^P1^S3^C%02d%s^S0^R0%s^P1", color, phrasing[r],
 | 
	
		
			
				|  |  | -      // restore_color);
 | 
	
		
			
				|  |  | -      ZF_LOGI("mangle(ANSI_CLS): Inserted (%02d) %s", color, phrasing[r]);
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        static LastSeen last_files(2);
 | 
	
		
			
				|  |  | +        int r;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        do {
 | 
	
		
			
				|  |  | +          r = randint((sizeof(possibles) / sizeof(file_need)));
 | 
	
		
			
				|  |  | +        } while (last_files.seen_before(r));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // (2); // (sizeof(possibles) / sizeof(file_need)) - 1);
 | 
	
		
			
				|  |  | +        needs_cls = possibles[r].cls;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // I get what's happening.  Mystic moves cursor to home, CLS, cursor
 | 
	
		
			
				|  |  | +        // home. When we get here, we're ALWAYS at the top of the screen...
 | 
	
		
			
				|  |  | +        // Hence our bat isn't displayed at the end of the screen.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // This is before the actual CLS, so we CLS before displaying our files.
 | 
	
		
			
				|  |  | +        // I tried a ^P2 before doing this .. but I'd rather have the picture up
 | 
	
		
			
				|  |  | +        // right away I think.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        sprintf(display, "%s^F%s.^P3%s", needs_cls ? "\x1b[2J" : "\n\r\n\r",
 | 
	
		
			
				|  |  | +                possibles[r].filename, restore_color);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ZF_LOGI("mangle(ANSI_CLS): %d file inserted %s", r, display);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Move the buffer so there's room for the display string.
 | 
	
		
			
				|  |  | +        if (string_insert(buffer, BSIZE * 4, cp - buffer, display)) {
 | 
	
		
			
				|  |  | +          ZF_LOGI("mangle(ANSI_CLS):");
 | 
	
		
			
				|  |  | +          ZF_LOGI_REPR(buffer);
 | 
	
		
			
				|  |  | +          ZF_LOGI("mangle(ANSI_CLS): [%s]", repr(buffer));
 | 
	
		
			
				|  |  | +          need_render = 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          /*
 | 
	
		
			
				|  |  | +          Copy the new buffer over, but hide our "render" code
 | 
	
		
			
				|  |  | +          from the remaining mangler steps.
 | 
	
		
			
				|  |  | +          */
 | 
	
		
			
				|  |  | +          strcpy(work, buffer);
 | 
	
		
			
				|  |  | +          i = cp - buffer;
 | 
	
		
			
				|  |  | +          // find offset into "buffer"
 | 
	
		
			
				|  |  | +          // apply to work.
 | 
	
		
			
				|  |  | +          memset(work + i, ' ', strlen(display));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      // Move the buffer so there's room for the display string.
 | 
	
		
			
				|  |  | -      if (string_insert(buffer, BSIZE * 4, cp - buffer, display)) {
 | 
	
		
			
				|  |  | -        ZF_LOGI("mangle(ANSI_CLS): [%s]", repr(buffer));
 | 
	
		
			
				|  |  | -        need_render = 1;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          ZF_LOGD("insert failed [%s].", repr(display));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  | -        ZF_LOGD("insert failed [%s].", repr(display));
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | +        if (random_activate(4)) {
 | 
	
		
			
				|  |  | +          int r;
 | 
	
		
			
				|  |  | +          char display[100] = "";
 | 
	
		
			
				|  |  | +          const char *phrasing[] = {"^R1Haha^P1ha^P1ha", "Poof!", "Got U",
 | 
	
		
			
				|  |  | +                                    "Anyone there?", "^R1Knock, ^P1Knock"};
 | 
	
		
			
				|  |  | +          static LastSeen last_phrasing(2);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          ZF_LOGI("mangle(ANSI_CLS)");
 | 
	
		
			
				|  |  | +          // sprintf( display, "^P2...");
 | 
	
		
			
				|  |  | +          // This string actually screws up ANSI detection (takes too long)
 | 
	
		
			
				|  |  | +          // strcpy(display, "^P2^S501234567890^P1abcdef^P2g^P3h^P4i^S0^P2");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // strcpy(display, "^P2^S301234^P15^S0^P2");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // Add in random text, plus color!
 | 
	
		
			
				|  |  | +          do {
 | 
	
		
			
				|  |  | +            r = random() % ((sizeof(phrasing) / sizeof(char *)) - 1);
 | 
	
		
			
				|  |  | +          } while (last_phrasing.seen_before(r));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          int color = random() % 15 + 1;
 | 
	
		
			
				|  |  | +          int x = random() % 30 + 1;
 | 
	
		
			
				|  |  | +          int y = random() % 15 + 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          /*
 | 
	
		
			
				|  |  | +          Don't have it pause there before moving the cursor.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          Move the cursor, get the color changed, THEN pause.
 | 
	
		
			
				|  |  | +          Then act all crazy.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          NOTE:  Make sure if you use any ^R Render effects, turn them off
 | 
	
		
			
				|  |  | +          before trying to display the restore_color.  :P   ^R0 Also, make
 | 
	
		
			
				|  |  | +          sure you re-home the cursor ^G0101 because that's where they are
 | 
	
		
			
				|  |  | +          expecting the cursor to be!  (At least it's how Mystic does it.)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          HOME, CLS, HOME, ...  Not sure what others do there.  We'll see.
 | 
	
		
			
				|  |  | +          */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          sprintf(display, "^G%02d%02d^S3^C%02d^P1%s^S0^R0%s^P1^G0101", x, y,
 | 
	
		
			
				|  |  | +                  color, phrasing[r], restore_color);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // sprintf(display, "^P1^S3^C%02d%s^S0^R0%s^P1", color, phrasing[r],
 | 
	
		
			
				|  |  | +          // restore_color);
 | 
	
		
			
				|  |  | +          ZF_LOGI("mangle(ANSI_CLS): Inserted (%02d) %s", color, phrasing[r]);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          // Move the buffer so there's room for the display string.
 | 
	
		
			
				|  |  | +          if (string_insert(buffer, BSIZE * 4, cp - buffer, display)) {
 | 
	
		
			
				|  |  | +            ZF_LOGI("mangle(ANSI_CLS):");
 | 
	
		
			
				|  |  | +            ZF_LOGI_REPR(buffer);
 | 
	
		
			
				|  |  | +            ZF_LOGI("mangle(ANSI_CLS): [%s]", repr(buffer));
 | 
	
		
			
				|  |  | +            need_render = 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            /*
 | 
	
		
			
				|  |  | +            Copy the new buffer over, but hide our "render" code
 | 
	
		
			
				|  |  | +            from the remaining mangler steps.
 | 
	
		
			
				|  |  | +            */
 | 
	
		
			
				|  |  | +            strcpy(work, buffer);
 | 
	
		
			
				|  |  | +            i = cp - buffer;
 | 
	
		
			
				|  |  | +            // find offset into "buffer"
 | 
	
		
			
				|  |  | +            // apply to work.
 | 
	
		
			
				|  |  | +            memset(work + i, ' ', strlen(display));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      // memmove(cp + strlen(display), cp, strlen(cp) + 1);
 | 
	
		
			
				|  |  | -      // strncpy(cp, display, strlen(display));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      /*
 | 
	
		
			
				|  |  | -      Copy the new buffer over, but hide our "render" code
 | 
	
		
			
				|  |  | -      from the remaining mangler steps.
 | 
	
		
			
				|  |  | -      */
 | 
	
		
			
				|  |  | -      strcpy(work, buffer);
 | 
	
		
			
				|  |  | -      i = cp - buffer;
 | 
	
		
			
				|  |  | -      // find offset into "buffer"
 | 
	
		
			
				|  |  | -      // apply to work.
 | 
	
		
			
				|  |  | -      memset(work + i, ' ', strlen(display));
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            ZF_LOGD("insert failed [%s].", repr(display));
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    strcpy(work, buffer); // sure.
 | 
	
	
		
			
				|  | @@ -1414,6 +1538,8 @@ int mangle(int fd, char *buffer) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  ZF_LOGD("work now:");
 | 
	
		
			
				|  |  | +  ZF_LOGD_REPR(work);
 | 
	
		
			
				|  |  |    ZF_LOGD("Work Now: [%s]", repr(work));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef OLD_WAY
 | 
	
	
		
			
				|  | @@ -1524,21 +1650,21 @@ int main(int argc, char *argv[]) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    srandom(time(NULL));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML1 -SL0 -ST2 -CUnknown -Ubugz
 | 
	
		
			
				|  |  | -  // -PUWISHPASSWORD
 | 
	
		
			
				|  |  | +  // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML1 -SL0 -ST2 -CUnknown
 | 
	
		
			
				|  |  | +  // -Ubugz -PUWISHPASSWORD
 | 
	
		
			
				|  |  |    // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML0 -SL0 -ST0 -CUnknown
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML1 -SL0 -ST2 -CUnknown -Ubugz
 | 
	
		
			
				|  |  | -  // -PUWISH
 | 
	
		
			
				|  |  | +  // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML1 -SL0 -ST2 -CUnknown
 | 
	
		
			
				|  |  | +  // -Ubugz -PUWISH
 | 
	
		
			
				|  |  |    // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML0 -SL0 -ST0 -CUnknown
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML0 -SL0 -ST0 -CUnknown
 | 
	
		
			
				|  |  |    // ./mystic -TID9 -IP192.168.0.1 -HOSTUnknown -ML0 -SL1 -ST0 -CUnknown
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML1 -SL0 -ST2 -CUnknown -Ubugz
 | 
	
		
			
				|  |  | -  // -PDUMBWAYTODOTHIS
 | 
	
		
			
				|  |  | -  // ./mystic -TID9 -IP192.168.0.1 -HOSTUnknown -ML1 -SL1 -ST2 -CUnknown -Ubugz
 | 
	
		
			
				|  |  | -  // -PIDONTUSEPASCAL
 | 
	
		
			
				|  |  | +  // ./mystic -TID7 -IP192.168.0.1 -HOSTUnknown -ML1 -SL0 -ST2 -CUnknown
 | 
	
		
			
				|  |  | +  // -Ubugz -PDUMBWAYTODOTHIS
 | 
	
		
			
				|  |  | +  // ./mystic -TID9 -IP192.168.0.1 -HOSTUnknown -ML1 -SL1 -ST2 -CUnknown
 | 
	
		
			
				|  |  | +  // -Ubugz -PIDONTUSEPASCAL
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // SSH:  -ML1 -ST2
 | 
	
		
			
				|  |  |    // Telnet: -ML0 -ST0
 |