Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TinyWar does exist! Here it is...

36 views
Skip to first unread message

Jason Downs

unread,
Oct 15, 1990, 1:23:00 AM10/15/90
to

The subject says it all. I dug around, found the archive, and fixed it up a
bit. Since it isn't safe to post this via anon FTP, I decided to cost the net
"hundreds, if not thousands" of dollars. So, here it is.

File: tinywar.shar
Type 'sh tinywar.shar', edit a couple #defines in tl.h, and type 'make'.

Send thank-you's to: dow...@jacobs.cs.orst.edu
Send flames to: en...@bigtime.covs.or.us

-Eniac

Cut here-----------------------------------------------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: tinywar/HELP1 tinywar/Makefile tinywar/command.c
# tinywar/config.c tinywar/fred.c tinywar/gag.c tinywar/history.c
# tinywar/keyboard.c tinywar/log.c tinywar/macro.c tinywar/process.c
# tinywar/random.c tinywar/special.c tinywar/stuff.c
# tinywar/tinytalk.doc tinywar/tinywar.doc tinywar/tl.h tinywar/tp.h
# tinywar/util.c tinywar/wrap.c
# Wrapped by dow...@jacobs.CS.ORST.EDU on Sun Oct 14 21:27:23 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test ! -d 'tinywar' ; then
echo shar: Creating directory \"'tinywar'\"
mkdir 'tinywar'
fi
if test -f 'tinywar/HELP1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/HELP1'\"
else
echo shar: Extracting \"'tinywar/HELP1'\" \(11289 characters\)
sed "s/^X//" >'tinywar/HELP1' <<'END_OF_FILE'
X
X@@@@summary--
XCommand help is avaliable on the following:
X
XBAMF BEEP BELL DEF
XGAG HELP HILITE INTR
XKILL LISTDEF LISTHILITE LOADDEF
XLOADGAG LOADHILITE LOG LOGIN
XLOGME NAMEWATCH NOGAG NOHILITE
XNOINTR NOLOG PS PURGEHILITE
XQUIET QUIT QUOTE RANDOM
XRECALL REPEAT REPLY SAVEDEF
XSH STTY UNDEF VERSION
XWATCHDOG WATCHNAME WRAP
X
Xhistory macro substitition tinywar
Xprocesses trouble wildcards
X
XWords in uppercase are functions and can be called with /function_name,
Xwhile words in lowercase are subjects on which extra help is avaliable.
X
XYou can read help on these subjects with /help subject_name, with subject
Xname being any of the above.
X
X@@@@help--
X
X Format: /help [function]
X
X Help prints out a command summary, or information about a
X command. The [function] argument is optional, and any
X function listed in the command summary given by /help with
X no arguments has a long description.
X
X Also see: summary
X
X@@@@quit--
X
X Format: /quit
X
X Quit gets out out of the tinytalk program, no questions
X asked.
X
X Also see: intr,nointr
X
X@@@@intr--
X
X Format: /intr [on|off]
X
X The intr function enables or disables Control-C and Control-Z
X interrupts. Most UNIX implementations will put a job into the
X background upon receiving Control-Z, and quit the program upon
X receiving a Control-C. Tinywar will ask you if you reall want
X to quit if it receives Control-C with interrupts enabled.
X
X Intr called with no arguments will display current interrupt
X handling status.
X
X Also see: quit, nointr
X
X@@@@nointr--
X
X Format: /nointr
X
X This function is identical to calling /intr with argument off.
X It's included for tinytalk 1.1 compatibility.
X
X Also see: intr, quit
X
X@@@@beep--
X
X Format: /beep [on|off|<number>]
X
X This function sets the number of beeps to send to the users's
X terminal when /bell is called. /beep on turns on beeping,
X /beep off turns off beeping, and /beep <number> turns on beeping
X and sets <number>.
X
X /beep called with no arguments will display current beep status.
X
X Also see: bell, nobeep
X
X@@@@nobeep --
X
X Format: /nobeep
X
X This function is identical to /beep off, and is included for
X tinytalk compatibility.
X
X Also see: beep, bell
X
X
X@@@@bell--
X
X Format: /bell
X
X When called then a number of bell characters will be sent to
X the user's terminal. The number of beeps can be set with /beep.
X
X This function is usefull for implementing a beeping hilite, as
X in
X
X /hilite You sense that * is looking for you in * = /beep
X
X The above is tinywar interpreted code for tinytalk /hilite pages.
X
X Also see: beep, hilite
X
X@@@@def--
X
X Format: /def <macro_name> = <macro>
X
X This function is used to define user keyboard macros.
X
X Also see: macro, history, substitution
X
X@@@@gag--
X
X Format: /gag <pattern> [ = <action>]
X
X This function adds <pattern> to the gag list. What this means
X is that every time tinywar sees MUD input containing <pattern>,
X it will ignore this input. You, as the user, won't even know
X about it. <pattern> may, and should, contain wildcards.
X
X The optional <action> argument will send the string <action>
X to MUD when <patten> is gagged. For example,
X
X /gag TinyDick * = whisper TinyDick = Please shut up.
X
X will ignore anything said by TinyDick, and whisper "Please shut
X up." to the said worthy every time he/she does something. The
X gag/hilite/act actions can be macro calls, they can have
X embedded newline characters (%; and %\) and name substitution
X character %n. %n will be substituted with the name of the
X last acting person, so
X
X /gag TinyDick * = whisper %n = Please shut up.
X
X will do exactly the same thing as the above gag.
X
X
X A common newbie mistake is to do a /gag TinyDick without the
X splat at the end, and expect /gag to work exactly like in
X tinytalk. Nope, sorry. You need the wildcard character to
X match all of TinyDick's actions. It's not a bug, it's a
X feature.
X
X /gag is of lower priority than /hilite, and will be overriden
X by /hilite. Not-gagging can be implemeted with /gag * and
X /hilite <friends>.
X
X Also see: reply, nogag, listgag, purgegag, act, hilite, wildcards
X
X@@@@hilite--
X
X Format: /hilite <pattern> [ = <action>]
X
X This function is a close cousin of /gag. Instead of ignoring
X input containing <pattern>, however, this function will hilite
X the lines containing <pattern>. Pattern may (and should)
X contain wildcards. The optional <action> argument also works
X exactly as in /gag.
X
X Autogreets can be implemented with
X
X /hilite * has arrived. = :waves to %n.
X
X for example. Do a help gag for more information on arguments to
X this function.
X
X Also see: gag, reply, listhilite, purgehilite, nohilite, wildcards, act
X
X@@@@act --
X
X Format: /act <pattern> [ = <action>]
X
X This function is a /hilite without the hilite. It will
X process <action> the same way /gag and /hilite will.
X
X As in /gag and /hilite, <pattern> will be matched using
X wildcard matching.
X
X Also see: gag, hilite, reply, listact, purgeact, noact, wildcards
X
X@@@@reply --
X
X Format: /reply [ON|OFF]
X
X This function controlls controls whether or not /gag and
X /hilite actions will be processed. With /reply on (the
X default) actions will be processed. /reply off turns you
X into a good mud.citizen. /reply called with no arguments
X will show you your reply status.
X
X Also see: gag, hilite, act
X
X@@@@bamf--
X
X Format: /bamf [on|off]
X
X Restrict bamfing around muds caused by portals. In the original
X tinytalk, if you saw a message matching #### Please reconnect ...
X you were mercilessly and unceremonisously reconnected. With
X /bamf off this won't happen.
X
X /bamf on restores tinytalk's portal handling.
X
X /bamf called with no arguments prints current /bamf status.
X
X See also: world, connect
X
X@@@@tinywar --
X
X The program you are using now. Tinywar is a modified tinytalk,
X the later program originally written by Anton Rang. It's a
X telnet clone, with MUD-specific features. The differences between
X tinywar, tinytalk and telnet are too numerous to mention in a
X short help, and I suggest that you read the source code, notably
X command.c to get a better understanding of tinytalk/tinywar.
X
X See also: summary
X
X@@@@wildcards --
X
X Wildcards refer to the pattern matching ability of tinywar. In
X specific, the characters '*' and '?'.
X
X The character '*', (referred to as a "splat") will match any number
X of characters, of any type. When wildcard matching is used to compare
X strings, "d*g" will match "drug" and "dog", where tinywar is concerned. A match happens with any word that starts with d and ends with g,
X including "dg".
X
X The '?' will match any one character. So "d?g" will also match "dog",
X "dig", and, in fact, any 3 letter word starting with 'd' and ending
X with 'g'. It will not match "dg" and "drug" like "d*g" will,
X though.
X
X If a function uses wildcard matching to compare strings, that will
X be mentioned in the help.
X
X Also see: hilite, gag, recall
X
X@@@@recall --
X
X Format: /recall [number][<pattern>]
X
X Tinywar saves all of it's received input in a recall buffer.
X You can print out the last number lines of this buffer with
X /recall number. You can also recall only those lines that
X include <pattern> by including the <pattern> in the function
X call. <pattern> may (and should) include wildcards, and is
X not case sensitive. For example,
X
X /recall 100 Grod*
X
X will print out all the output from yours truly in the last 100
X lines. /recall with no arguments will print out the last 24
X lines recieved.
X
X Also see: history, substitution
X
X@@@@history --
X
X Format: Control-P, Control-N
X
X Tinywar also saves most of your input in a history buffer.
X You can move through this buffer using ^N and ^P, where
X '^' is not an up carrett, but rather a held down Control
X key.
X
X You can edit this line, and hitting return sends it to MUD.
X
X Also see: substitution, recall
X
X@@@@substitution --
X
X Format: ^string1^string2
X
X This is a quick way to fix your mistakes. In this case,
X '^' is the up-carrett character, not a held down control
X key. Tinywar will find the first occurance of string1
X in your history buffer, replace it with string2, and send
X the output to MUD. For example, suppose you typed
X
X whisler Player = Incredibly huge, voluminous, enormous message.
X
X only to be thanked by a Huh? message. No problem, do a
X
X ^whisler^whisper
X
X and you're set. You can't edit modified lines, and substutition is
X case-sensitive.
X
X See also: history, recall
X
X@@@@macro --
X
X Format: /def macro_name = macro text.
X
X This defines a tinywar keyboard macro. The macro can
X be called with /macro_name [arguments]. So after a
X
X /def foo = :bars around.
X
X you can type /foo and MUD will receive :bars around. Simplicity
X itself.
X
X You can also insert arguments into the macro. Strings %1 through
X %4 will be replaced with arguments 1 through 4, if such are given
X with the macro call. %* will insert ALL of the arguments the
X macro was called with, and %n will insert the name of the last
X person acting. So
X
X /def bonk = :BONKs %1 %2.
X
X called with /bonk Player lightly will send :BONKs Player lightly.
X The same result would have been achieved with
X
X /def bonk = :BONKs %*.
X
X Macro can have imbedded newlines, the characters for which are
X %; and %\. For example,
X
X /def foo = :foos%;:bars
X
X will send :foos and :bars to MUD.
X
X You can have other macro/function calls after the embedded
X newline characters.
X
X Also see: loaddef, savedef, listdef, undef, purgedef
X
X@@@@ loaddef --
X
X Format: /loaddef [[pathname]<filename>]
X
X Load macro definition file <filename>. If the optional
X argument <filename> is not given, then the default file
X ~/tiny_macros is loaded.
X
X Also see: def, savedef, listdef, undef, purgedef
X
X@@@@ savedef --
X
X Format: /savedef [[pathname]<filename>]
X
X Save macro definition file <filename>. If the optional
X argument <filename> is not given, then the default file
X ~/tiny_macros is saved.
X
X Also see: def, loaddef, listdef, undef, purgedef
X
X@@@@ newlines --
X
X Format: %; or %\
X
X Newlines characters can be put anywhere, and upon output to
X MUD they will be replaced with the actual newline character.
X
X So typing
X
X :foo%;/bar
X
X is equivalent to typing
X
X :foo
X /bar
X
X as far as the remote MUD is concerned.
X
X Newline characters can be used anywhere, and any commands that
X follow will be processed by tinywar.
X
X A common mistake in making nested macros is typing
X
X /def foo = /bar%;/baz
X
X and then wondering at the error message. Well, wonder not.
X Tinywar thinks that /bar%;/baz is the full name of a function,
X since it hasn't processed %; yet. Try
X
X /def foo = /bar %;/baz.
X
X@@@@trouble --
X
X In case you find a bug or have a gripe, don't sit there moping.
X Send me a bug report and/or your ideas. I guarantee a fixed
X version within the week.
X
X The adress is plo...@snoopy.colorado.edu (and will be for the
X 1990/91 school year), and contrary to popular belief I don't bite.
X Very hard.
X
X@@@@
X
END_OF_FILE
if test 11289 -ne `wc -c <'tinywar/HELP1'`; then
echo shar: \"'tinywar/HELP1'\" unpacked with wrong size!
fi
# end of 'tinywar/HELP1'
fi
if test -f 'tinywar/Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/Makefile'\"
else
echo shar: Extracting \"'tinywar/Makefile'\" \(326 characters\)
sed "s/^X//" >'tinywar/Makefile' <<'END_OF_FILE'
XCC = cc
XCFLAGS = -DTERMCAP -O -DDEBUG
XLIBRARIES = -ltermcap
X
XOBJECTS = fred.o config.o util.o stuff.o keyboard.o wrap.o log.o macro.o \
X command.o special.o gag.o history.o random.o process.o
X
Xall: tinywar
X
Xtinywar: $(OBJECTS)
X $(CC) $(CFLAGS) -o tinywar $(OBJECTS) $(LIBRARIES)
X
Xclean:
X rm -f $(OBJECTS)
X
X$(OBJECTS): tl.h
END_OF_FILE
if test 326 -ne `wc -c <'tinywar/Makefile'`; then
echo shar: \"'tinywar/Makefile'\" unpacked with wrong size!
fi
# end of 'tinywar/Makefile'
fi
if test -f 'tinywar/command.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/command.c'\"
else
echo shar: Extracting \"'tinywar/command.c'\" \(19274 characters\)
sed "s/^X//" >'tinywar/command.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk command line processing. */
X/* */
X/* Version.1.0 [ 1/25/90] : Initial implementation by ABR. */
X/* .1.1 [ 1/26/90] : Added additional commands. */
X/* .1.2 [ 1/26/90] : Added additional commands. */
X/* .1.3 [ 2/ 2/90] : Yet more commands; use binary search. */
X/* 1.4 [ 2/ 5/90] : A few more commands; world switching. */
X/* 1.5 [ 2/ 5/90] : Fixed /savehilite | /loadhilite. */
X/* 1.6 [ 3,4 90] : added /whispergag, /sh; commands now */
X/* more/less orthogonal. */
X/* 1.9 [ 5/14/90] : add everything up to /namechange */
X/* 1.2.0 [ 6/26/90] : nuked redundant commands like /whisper*/
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X#include <fcntl.h>
X
X
X#define ON ((args[0] == 'o') && (args[1] == 'n') && (args[2] < 'A'))
X
X#define OFF ((args[0] == 'o') && (args[1] == 'f') && (args[2] == 'f') && (args[3] < 'A'))
X
Xint bomf = 0; /* bomf between worlds? */
Xint lpmud = 0; /* special lp-mud io/flushing */
Xsmallstr ourpasswd;
X
Xextern char *index(),*strstr();
Xextern world_rec *find_world(), *get_default_world(), *get_world_header();
Xextern int *send_quote();
Xextern int do_repeat();
Xextern void do_kill();
Xextern void do_ps();
X
X /* There are enough commands now that a hash table or binary search */
X /* is preferable. We'll use a binary search. */
X
Xint handle_wrap_command(),
X handle_log_command(),
X handle_logme_command(),
X handle_version_command(),
X handle_lpmud_command(),
X handle_def_command(),
X handle_undef_command(),
X handle_savedef_command(),
X handle_listdef_command(),
X handle_listwatchdog_command(),
X handle_loaddef_command(),
X handle_quiet_command(),
X handle_login_command(),
X handle_help_command(),
X handle_quit_command(),
X handle_intr_command(),
X handle_beep_command(),
X handle_stty_command(),
X handle_gag_command(),
X handle_nogag_command(),
X handle_savegag_command(),
X handle_loadgag_command(),
X handle_listgag_command(),
X handle_hilite_command(),
X handle_nolog_command(),
X handle_nohilite_command(),
X handle_loadact_command(),
X handle_loadhilite_command(),
X handle_savehilite_command(),
X handle_listhilite_command(),
X handle_listworlds_command(),
X handle_world_command(),
X handle_shell_command(),
X handle_reply_command(),
X handle_quote_command(),
X handle_repeat_command(),
X handle_bamf_command(),
X handle_random_command(),
X handle_recall_command(),
X handle_purgegag_command(),
X handle_purgehilite_command(),
X handle_purgedef_command() ,
X handle_ps_command(),
X handle_watchdog_command(),
X handle_nowatchdog_command(),
X handle_watchname_command(),
X handle_act_command(),
X handle_noact_command(),
X handle_listact_command(),
X handle_purgeact_command(),
X handle_kill_command()
X
X#ifdef NAMECHANGE
X ,handle_autonamechange_command()
X ,handle_namechange_command()
X#endif
X ;
X
Xint handle_macro_command();
X
Xtypedef struct cmd_entry {
X char *name;
X int (*func)();
X} cmd_entry;
X
X /* It is IMPORTANT that the commands be in alphabetical order! */
X
Xstatic cmd_entry cmd_table[] =
X{
X { "ACT", handle_act_command},
X#ifdef NAMECHANGE
X { "AUTONAMECHANGE", handle_autonamechange_command},
X#endif;
X { "BEEP", handle_beep_command },
X { "BAMF", handle_bamf_command },
X { "DEF", handle_def_command },
X { "GAG", handle_gag_command },
X { "HELP", handle_help_command },
X { "HILITE", handle_hilite_command },
X { "INTR", handle_intr_command },
X { "KILL", handle_kill_command },
X { "LISTACT", handle_listact_command },
X { "LISTDEF", handle_listdef_command },
X { "LISTGAG", handle_listgag_command },
X { "LISTHILITE", handle_listhilite_command },
X { "LISTWATCHDOG", handle_listwatchdog_command },
X { "LISTWORLDS", handle_listworlds_command },
X { "LOADACT", handle_loadact_command },
X { "LOADDEF", handle_loaddef_command },
X { "LOADGAG", handle_loadgag_command },
X { "LOADHILITE", handle_loadhilite_command },
X { "LOG", handle_log_command },
X { "LOGIN", handle_login_command },
X { "LOGME", handle_logme_command },
X { "LPMUD", handle_lpmud_command },
X#ifdef NAMECHANGE
X { "NAMECHANGE", handle_namechange_command },
X#endif
X { "NOACT", handle_noact_command },
X { "NOGAG", handle_nogag_command },
X { "NOHILITE", handle_nohilite_command },
X { "NOLOG", handle_nolog_command },
X { "NOWATCHDOG", handle_nowatchdog_command },
X { "PS", handle_ps_command },
X { "PURGEACT", handle_purgeact_command },
X { "PURGEDEF", handle_purgedef_command },
X { "PURGEGAG", handle_purgegag_command },
X { "PURGEHILITE", handle_purgehilite_command },
X { "QUIET", handle_quiet_command },
X { "QUIT", handle_quit_command },
X { "QUOTE", handle_quote_command },
X { "RANDOM", handle_random_command },
X { "RECALL", handle_recall_command },
X { "REPEAT", handle_repeat_command },
X { "REPLY", handle_reply_command },
X { "SAVEDEF", handle_savedef_command },
X { "SAVEGAG", handle_savegag_command },
X { "SAVEHILITE", handle_savehilite_command },
X { "SH", handle_shell_command},
X { "STTY", handle_stty_command },
X { "UNDEF", handle_undef_command },
X { "VERSION", handle_version_command },
X { "WATCHDOG", handle_watchdog_command},
X { "WATCHNAME", handle_watchname_command},
X { "WORLD", handle_world_command },
X { "WRAP", handle_wrap_command }
X};
X
X#define NUM_COMMANDS (sizeof(cmd_table) / sizeof(cmd_entry))
X
Xint being_offensive = 1; /* are we going to reply to gaggee? */
X
Xhandle_command(cmd_line, is_config)
X register char *cmd_line;
X int is_config;
X{
X string cmd, args;
X register char *place;
X register char *tempchar;
X int (*handler)(), (*binary_search())();
X
X place = index(cmd_line, ' ');
X if (place == NULL) {
X strcpy(cmd, cmd_line + 1); /* Only have command. Ignore '/'. */
X args[0] = '\0';
X }
X else {
X *place = '\0'; /* Get rid of the space.... */
X strcpy(cmd, cmd_line + 1);
X strcpy(args, place + 1);
X *place = ' '; /* Put the space back! */
X }
X
X stripstr(cmd);
X stripstr(args);
X
X if (cmd[0] == '\0') /* Empty command, ignore it. */
X return;
X
X handler = binary_search(cmd);
X
X if (handler != NULL)
X (*handler)(args);
X else
X handle_macro_command(cmd, args); /* Assume it's a macro. */
X}
X
Xint (*binary_search(cmd))()
X register char *cmd;
X{
X register int bottom, top, mid, value;
X
X bottom = 0;
X top = NUM_COMMANDS - 1;
X
X while (bottom <= top) {
X mid = bottom + ((top - bottom) / 2);
X value = comparestr(cmd, cmd_table[mid].name);
X if (value == 0)
X return (cmd_table[mid].func);
X else if (value < 0)
X top = mid - 1;
X else
X bottom = mid + 1;
X }
X
X return (NULL);
X}
X
Xhandle_wrap_command(args) /* Toggle word wrap. */
X register char *args;
X{
X static short wordwrap= 1; /* start with wordwrap */
X
X if (*args) { /* if no args then list status */
X
X if ((args[0] >= '0') && (args[0] <= '9')) /* Verify starts numeric. */
X enable_wrap(atoi(args)); /* If argument, use it. */
X else
X if (OFF) /* '/wrap off' to turn off wordwrap */
X wordwrap = 0;
X else /* anything else to turn on */
X wordwrap = 1;
X }
X
X puts((wordwrap)?"% Wordwrap is enabled.":"% Wordwrap is disabled.");
X
X if(wordwrap)
X enable_wrap(0);
X else
X disable_wrap();
X}
X
X
Xhandle_log_command(args) /* Enable logging. */
X char *args;
X{
X static short logging = 0; /* log/nolog */
X
X if (*args) /* otherwise just show status */
X {
X if(OFF)
X logging = 0;
X else
X {
X logging = 1;
X if(ON)
X args += 3;
X }
X }
X puts((logging)?"% Logging is enabled.":"% Logging is disabled.");
X if (logging)
X enable_logging(args);
X else
X disable_logging();
X}
X
Xhandle_nolog_command(args)
X{
X disable_logging();
X puts("% Logging is disabled.");
X}
X
Xhandle_logme_command(args) /* Enable input logging. */
X char *args;
X{
X static short logme = 0; /* status of logme */
X
X if(OFF)
X logme = 0;
X else if (ON)
X logme = 1;
X
X puts((logme)?"% Logme is enabled.":"% Logme is disabled.");
X if(logme) enable_logme();
X else disable_logme();
X}
X
Xhandle_def_command(args) /* Define a macro. */
X register char *args;
X{
X register char *place;
X string name, body;
X
X place = index(args, '=');
X if (place == NULL) {
X fprintf(stderr,"%% No '=' in macro definition.\n");
X return;
X }
X
X *place = '\0';
X strcpy(name, args);
X strcpy(body, place + 1);
X stripstr(name);
X stripstr(body);
X
X add_macro(name, body);
X}
X
Xhandle_undef_command(args) /* Undefine a macro. */
X char *args;
X{
X remove_macro(args);
X}
X
Xhandle_savedef_command(args) /* Save macro definitions. */
X register char *args;
X{
X if (args[0] == '\0') /* No filename, use default. */
X strcpy(args, "~/tiny.macros");
X
X write_macros(args);
X}
X
Xhandle_macro_command(cmd, args) /* Invoke a macro. */
X char *args;
X{
X string expanded;
X int length;
X
X process_macro(cmd, args, expanded); /* Expand the body */
X if (expanded[0] == '\0') /* Catch failure (or empty). */
X return;
X
X length = strlen(expanded);
X while(expanded[--length] == '\n')
X expanded[length] = '\0'; /* strip off trailing newlines */
X old_process_buffer(expanded, length+1); /* and send it via link. */
X}
X
Xhandle_quiet_command(args) /* Turn on portal suppression. */
X char *args;
X{
X static short quiet = 0;
X
X if (ON) quiet = 1;
X else if (OFF) quiet = 0;
X
X puts((quiet)?"% Login message suppression is enabled."
X :"% Login message suppression is disabled.");
X if(quiet) set_quiet();
X else
X clear_quiet();
X}
X
Xhandle_login_command(args) /* Turn on automatic login. */
X char *args;
X{
X static short autologin = 0;
X if (ON) autologin = 1;
X else if (OFF) autologin = 0;
X
X puts((autologin)?"% Autologin is enabled.":"% Autologin is disabled.");
X if(autologin)
X enable_auto_login();
X else
X disable_auto_login();
X}
X
Xhandle_help_command(args) /* Give user some help. */
X char *args;
X{
X
X/* function expects a string that's the subject to help on, in lowercase.
X** It uses read to slorp in chunks of HELP1 (defined in tl.h) and a
X** sequential search to find \n@@@@subject, and prints out everyting
X** up to the next \n@@@@.
X*/
X int fd; /* help file descriptor */
X
X if(!args || !*args) {
X handle_help_command("summary");
X return;
X }
X if((fd = open(HELPDAT,O_RDONLY,0)) == -1) { /* error */
X printf("%% error in help: help file not found.\n");
X return;
X
X }
X else {
X hugestr helpbuffer;
X int l,found = 0;
X char *helpstr;
X
X while(!found && (l = read(fd,helpbuffer,HUGESTRLEN))) {
X
X helpstr = helpbuffer;
X helpbuffer[l] = '\0';
X
X while(helpstr = strstr(helpstr,args)) {
X if(!strncmp((helpstr - 5),"\n@@@@",5)) { /* found the entry */
X char *endhelp;
X int done = 0;
X register int len = strlen(helpstr);
X
X found = 1;
X
X printf("\n-- Information on ");
X
X strncpy(helpbuffer,helpstr,len); /* move to start */
X helpbuffer[len] = 0;
X while(!(endhelp = strstr(helpbuffer,"\n@@@@"))) {
X printf(helpbuffer);
X len = read(fd,helpbuffer,HUGESTRLEN);
X if(!len) {
X endhelp = helpbuffer;
X break;
X }
X helpbuffer[l] = 0;
X }
X *endhelp = 0;
X printf(helpbuffer);
X break;
X }
X else helpstr++;
X }
X }
X close(fd);
X if(!found)
X printf("%% Help on subject %s not found. Try all lowercase.\n",args);
X else
X printf("-- end help --\n");
X
X }
X}
X
Xhandle_listdef_command(args)
X char *args;
X{
X if (args[0] != '\0') {
X list_all_macros(args);
X }
X else
X list_all_macros(FALSE);
X}
X
Xhandle_loaddef_command(args)
X char *args;
X{
X do_file_load("/DEF ", args, "~/tiny.macros");
X}
X
Xhandle_quit_command(args)
X char *args;
X{
X set_done();
X}
X
Xhandle_beep_command(args)
X register char *args;
X{
X static short beep = 1; /* beep on page */
X
X if (ON) { /* default set beep to 3 beeps */
X beep = 1;
X set_beep(3);
X }
X else
X if (OFF) beep = 0;
X else
X if ((args[0] >= '0') && (args[0] <= '9')) { /* Verify starts numeric. */
X beep = 1;
X set_beep(atoi(args)); /* If argument, use it. */
X }
X puts((beep)?"% Beeping is enabled.":"% Beeping is disabled.");
X}
X
Xhandle_nobeep_command(args)
X char *args;
X{
X set_beep(0);
X}
X
Xhandle_intr_command(args)
X char *args;
X{
X static short interrupts = 0;
X
X if (ON) {
X interrupts = 1;
X allow_interrupts();
X } else if (OFF) {
X interrupts = 0;
X disallow_interrupts();
X }
X puts((interrupts)?"% Don't ask to quit on ctrl-c.":"% Ask to quit on ctrl-c.");
X}
X
X
Xhandle_stty_command(args)
X char *args;
X{
X static short sttyuse = 0;
X
X if (ON) {
X sttyuse = 1;
X use_stty();
X } else if (OFF) {
X no_use_stty();
X sttyuse = 0;
X }
X puts((sttyuse)?"% Using stty.":"% Not using stty.");
X}
X
Xhandle_gag_command(args)
X char *args;
X{
X if (args[0] == '\0')
X enable_gagging();
X else
X add_gag(args);
X}
X
Xhandle_nogag_command(args)
X char *args;
X{
X if (args[0] == '\0')
X disable_gagging();
X else
X remove_gag(args);
X}
X
Xhandle_listgag_command(args)
X char *args;
X{
X list_gag(args);
X}
X
Xhandle_loadgag_command(args)
X char *args;
X{
X do_file_load("/GAG ", args, "~/tiny.gag");
X}
X
Xhandle_savegag_command(args)
X char *args;
X{
X save_gag(args);
X}
X
Xhandle_hilite_command(args)
X register char *args;
X{
X if (args[0] == '\0')
X enable_hiliting();
X else
X add_hilite(args);
X}
X
Xhandle_act_command(args)
X register char *args;
X{
X
X if(!*args)
X enable_acting();
X else
X add_act(args);
X}
Xhandle_nohilite_command(args)
X register char *args;
X{
X if (args[0] == '\0')
X disable_hiliting();
X else
X remove_hilite(args);
X}
Xhandle_noact_command(args)
X register char *args;
X{
X if(!*args)
X disable_acting();
X else
X remove_act(args);
X}
Xhandle_listhilite_command(args)
X char *args;
X{
X list_hilite(args);
X}
X
Xhandle_loadhilite_command(args)
X char *args;
X{
X do_file_load("/HILITE ", args, "~/tiny.hilite");
X}
Xhandle_loadact_command(args)
X char *args;
X{
X do_file_load("/ACT ", args , "~/tiny.act");
X}
Xhandle_savehilite_command(args)
X char *args;
X{
X save_hilite(args);
X}
X
X /* Generic routine to load commands of a specified type from a file. */
X
Xdo_file_load(cmd, args, default_name)
X register char *cmd;
X char *args, *default_name;
X{
X register FILE *cmdfile;
X int done;
X string line;
X char temp[20]; /* Big enough for any command. */
X int length;
X
X length = strlen(cmd); /* Length of expected command. */
X
X if (args[0] == '\0') /* No filename, use default. */
X strcpy(args, default_name);
X
X expand_filename(args);
X
X cmdfile = fopen(args, "r");
X if (cmdfile == NULL)
X fprintf(stderr,"%% Couldn't open file %s.\n", args);
X else {
X done = FALSE;
X
X while (!done) {
X if (fgets(line, MAXSTRLEN, cmdfile) == NULL)
X done = TRUE;
X else {
X if (line[0] != '\0') /* Get rid of newline. */
X line[strlen(line)-1] = '\0';
X
X if ((line[0] == '\0') || (line[0] == ';')) /* Blank or comment. */
X continue;
X
X strncpy(temp, line, length); /* Length of command (incl. space). */
X temp[length] = '\0'; /* Terminate after command. */
X if (comparestr(temp, cmd)) {
X fprintf(stderr,"%% Illegal line: %s.\n", line);
X#ifdef TOUCHY
X done = TRUE;
X#endif
X }
X else {
X handle_command(line,FALSE); /* Process this recursively. */
X }
X }
X }
X fclose(cmdfile);
X }
X}
X
Xhandle_recall_command(args)
X char *args;
X{
X
X avoid_recall(); /* Don't record this! */
X
X if(!*args)
X do_printbuffer(0,0);
X else
X {
X char *temp = args;
X int number;
X
X if(number = atoi(args))
X temp = index(args,' '); /* whatever else will follow a number */
X if(temp)
X while(*temp == ' ')
X temp++;
X do_printbuffer(number,temp);
X }
X}
X
Xhandle_listworlds_command(args)
X char *args;
X{
X register world_rec *p;
X
X p = get_world_header();
X while (p != NULL) {
X printf("%% %s\n", p->world);
X p = p->next;
X }
X}
X
Xhandle_world_command(args)
X char *args;
X{
X char *place, ch;
X register world_rec *where;
X
X if (args[0] == '\0') {
X where = get_default_world();
X if (where == NULL) {
X fprintf(stderr, "%% No default world is set.");
X return;
X }
X }
X else {
X where = find_world(args);
X if (where == NULL) {
X fprintf(stderr, "%% The world %s is unknown.", args);
X return;
X }
X }
X
X if (connect_to(where))
X magic_login();
X else
X fprintf(stderr,"%% Connection to world %s failed.\n", where->world);
X}
X
Xint handle_shell_command(args)
X char *args;
X{
X register char *place = args;
X
X cooked_echo_mode();
X system(place);
X cbreak_noecho_mode();
X}
X
Xint handle_quote_command(args) /* quote a file to other users. */
X char *args;
X{
X if(!*args) /* no argument */
X fprintf(stderr,"%% Quote what? \n");
X else send_quote(args);
X}
X
Xint handle_reply_command(args)
X char *args;
X{
X if (ON) being_offensive = 1;
X else if (OFF) being_offensive = 0;
X
X puts((being_offensive)?"% You are now truly offensive.":
X "% You are not as offensive.");
X}
X
Xint handle_bamf_command(args)
Xchar *args;
X{
X if(args && *args) {
X if (ON)
X bomf = 1;
X else if (OFF)
X bomf = 0;
X else
X do_login(args);
X }
X puts((bomf)?"% Bomfing is enabled.":"% Bomfing is disabled.");
X}
X
X
Xint handle_repeat_command(args) /* repeat action n times */
X char *args;
X{
X if(*args) {
X char *temp;
X
X if(!index(args,'\n'))
X strcat(args,"\n");
X temp = index(args,' ') + 1;
X newproc(atoi(args),do_repeat,temp,strlen(temp),-1);
X }
X}
X
Xint handle_purgedef_command(args)
X char *args;
X{
X purgemacro(args);
X}
X
Xint handle_purgegag_command(args)
Xchar *args;
X{
X purgegag(args);
X}
Xint handle_purgehilite_command(args)
X char *args;
X{
X purgehilite(args);
X}
Xint handle_purgeact_command(args)
X char *args;
X{
X purgeact(args);
X}
X#ifdef NAMECHANGE
Xint handle_autonamechange_command(args)
Xchar *args;
X{
X if(!*args) {
X puts("%% Autonamechange is %s.\n",(autonamechange)?"on":"off");
X return;
X }
X if(ON) {
X if(ourpasswd[0])
X autonamechange = 1;
X else
X puts("%% No password defined.\n");
X return;
X }
X if(OFF) {
X autonamechange = 0;
X return;
X }
X autonamechange = 1;
X strcpy(ourpasswd,args);
X}
X
Xint handle_namechange_command(args)
X char *args;
X{
X if(args) /* args is password */
X do_namechange(args);
X}
X#endif
X
Xint handle_kill_command(args)
X char *args;
X{
X
X if (args)
X do_kill(atoi(args));
X}
X
Xint handle_ps_command(args)
X char *args;
X{
X do_ps();
X}
Xint handle_nowatchdog_command(args)
X char *args;
X{
X disable_watchdog();
X}
Xint handle_listwatchdog_command(args)
X char *args;
X{
X announce_watchdog();
X}
Xint handle_watchdog_command(args)
X char *args;
X{
X if(OFF)
X disable_watchdog(); /* dept of redundancy dept */
X else if (ON)
X enable_watchdog("");
X else
X enable_watchdog(args);
X}
X
Xint handle_watchname_command(args)
X char *args;
X{
X if(ON)
X enable_namewatch("");
X else
X if(OFF)
X disable_namewatch();
X else
X enable_namewatch(args);
X}
X
Xhandle_listact_command(args)
Xchar *args;
X{
X list_act(args);
X}
X
Xhandle_lpmud_command(args)
Xchar *args;
X{
X if(ON)
X lpmud = 1;
X else if (OFF)
X lpmud = 0;
X
X fprintf(stdout,"%% Lpmud flushing is %s.\n",(lpmud)?"on":"off");
X}
X
Xhandle_version_command(args)
Xchar *args;
X{
X fprintf(stdout,"%% Congratulations. You're using %s.\n",VERSION);
X}
END_OF_FILE
if test 19274 -ne `wc -c <'tinywar/command.c'`; then
echo shar: \"'tinywar/command.c'\" unpacked with wrong size!
fi
# end of 'tinywar/command.c'
fi
if test -f 'tinywar/config.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/config.c'\"
else
echo shar: Extracting \"'tinywar/config.c'\" \(3748 characters\)
sed "s/^X//" >'tinywar/config.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk configuration file support. */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* 1.1 [ 1/25/90] : Added comments. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X
Xextern char *malloc(), *getenv();
X
Xstatic world_rec *the_worlds, *default_world;
X
Xint read_configuration()
X{
X string config_name;
X register FILE *config_file;
X
X get_file_name(config_name);
X config_file = fopen(config_name, "r");
X if (config_file == NULL) {
X/* fprintf(stderr, "Couldn't open configuration file %s .\n", config_name); */
X return (1); /* Succeed even so. */
X }
X
X parse_configuration(config_file); /* Ignore any errors. */
X
X fclose(config_file); /* Hope it works.... */
X
X return (1); /* Always succeed, this is optional. */
X}
X
Xget_file_name(s)
X register char *s;
X{
X register char *env;
X
X env = getenv("TINYTALK"); /* Check TINYTALK first. */
X if (env != NULL)
X strcpy(s, env);
X else
X strcpy(s, HOMEDIR); /* 1.2.2.1 - downsj */
X expand_filename(s);
X}
X
Xparse_configuration(f)
X FILE *f;
X{
X if (parse_worlds(f)) /* Returns 0 at EOF or error */
X parse_commands(f);
X}
X
Xint parse_worlds(f)
X FILE *f;
X{
X string line;
X int done, eof_flag;
X
X the_worlds = NULL;
X default_world = NULL;
X done = FALSE;
X eof_flag = FALSE;
X
X while (!done) {
X if (fgets(line, MAXSTRLEN, f) == NULL) {
X done = TRUE;
X eof_flag = TRUE;
X continue;
X }
X
X if (line[0] == ';') /* Comment */
X continue;
X
X line[strlen(line)-1] = '\0'; /* Strip newline */
X
X if (line[0] == '\0') { /* Blank line? */
X done = TRUE;
X continue;
X }
X
X if (!add_world(line))
X done = TRUE;
X }
X
X return (!eof_flag);
X}
X
Xint add_world(line) /* *** WARNING, LENGTH LIMITED *** */
X char *line;
X{
X register world_rec *new;
X int count;
X
X new = (world_rec *) malloc(sizeof(world_rec));
X count = sscanf(line, "%31s %31s %31s %31s %31s", new->world, new->character,
X new->pass, new->address, new->port);
X if (count == 3) { /* No address info */
X *(new->address) = '\0';
X *(new->port) = '\0';
X goto done;
X }
X else if (count == 5) { /* All info specified */
X if (!strcmp(new->world, "default"))
X fprintf(stderr,"Warning: address for default world ignored");
X goto done;
X }
X else {
X fprintf(stderr,"Could not parse: %s .\n", line);
X return (0);
X }
X
Xdone:
X
X if ((the_worlds == NULL) && (count == 5)) /* Set up default world, */
X default_world = new; /* if first one and all info. */
X
X new->next = the_worlds;
X the_worlds = new;
X
X return (1);
X}
X
Xparse_commands(f)
X FILE *f;
X{
X /* All commands ought to be the same as from the keyboard. */
X /* We hand them over there for processing. */
X
X string line;
X int done;
X
X done = FALSE;
X
X while (!done) {
X if (fgets(line, MAXSTRLEN, f) == NULL) {
X done = TRUE;
X break;
X }
X
X line[strlen(line)-1] = '\0'; /* Strip newline */
X
X if ((line[0] == '\0') || (line[0] == ';')) /* Blank line or comment. */
X continue; /* Ignore it. */
X
X if (*line != '/') { /* Not a command! */
X fprintf(stderr,"Not a command: %s .\n", line);
X continue;
X }
X
X handle_command(line, TRUE); /* Special-case errors since we */
X /* aren't started up yet. */
X } /* Actually, doesn't do anything now. */
X
X}
X
Xworld_rec *get_default_world()
X{
X return (default_world);
X}
X
Xworld_rec *find_world(name)
X register char *name;
X{
X register world_rec *p;
X
X p = the_worlds;
X while ((p != NULL) && !(equalstr(p->world, name)))
X p = p->next;
X
X return(p);
X}
X
Xworld_rec *get_world_header()
X{
X return (the_worlds);
X}
END_OF_FILE
if test 3748 -ne `wc -c <'tinywar/config.c'`; then
echo shar: \"'tinywar/config.c'\" unpacked with wrong size!
fi
# end of 'tinywar/config.c'
fi
if test -f 'tinywar/fred.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/fred.c'\"
else
echo shar: Extracting \"'tinywar/fred.c'\" \(3435 characters\)
sed "s/^X//" >'tinywar/fred.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk : Connect to a TinyMUD world. */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* Contact ra...@cs.wisc.edu for support. */
X/* */
X/* 1.1 [ 2/ 2/90] : Added many new commands; reorganized */
X/* some files. */
X/* */
X/* This program connects to a TinyMUD world via the TELNET protocol. */
X/* It provides the following features: */
X/* */
X/* Portal recognition: Some TinyMUD systems have portals to other */
X/* worlds. TinyTalk deals with these correctly. */
X/* */
X/* Word wrap: If word wrap is desired, it may be enabled. */
X/* */
X/* Command refresh: When TinyMUD prints a message, the command line */
X/* typed so far is reprinted. */
X/* */
X/* Macros: Simple macros may be defined. */
X/* */
X/* Configuration file: Characters, parameters, and macros may be set */
X/* automatically. */
X/* */
X/* Page handling: Pages may trigger beeps. */
X/* */
X/* Gags: Messages from certain characters or robots may be ignored. */
X/* */
X/************************************************************************/
X
X#include <stdio.h>
X#include "tl.h"
X
Xextern world_rec *get_default_world(), *find_world();
Xextern char *malloc();
X
Xworld_rec *boot_world();
X
Xmain(argc, argv)
X int argc;
X char *argv[];
X{
X world_rec *first_world;
X
X clear_quiet(); /* Initialize subsystems. */
X init_logging(); /* Don't do keyboard yet, though. */
X srandom(getpid()); /* for /random and namechange */
X#ifdef NAMECHANGE
X loadnames(); /* name array inited */
X#endif
X init_macros();
X enable_auto_login();
X enable_wrap(0); /* Enable default wrapping. */
X set_beep(3); /* Set default beep mode. */
X init_gagging();
X preinit_keyboard(); /* Initialization before */
X /* config file is read. */
X
X read_configuration();
X first_world = boot_world(argc, argv);
X
X init_keyboard();
X do_stuff(first_world);
X}
X
Xworld_rec *boot_world(argc, argv)
X register int argc;
X register char *argv[];
X{
X register world_rec *temp;
X
X if ((argc >= 2) && (!strcmp(argv[1], "-"))) { /* Option '-'. */
X disable_auto_login();
X --argc;
X argv++;
X }
X
X if (argc == 1) { /* Try default world */
X temp = get_default_world();
X
X if (temp == NULL)
X die("%% You must specify a world; there is no default set.\n");
X else /* Have a default. */
X return (temp);
X }
X else if (argc == 2) { /* World specified. */
X if (argv[1][0] == '-') { /* Check for '-' option */
X disable_auto_login();
X argv[1]++;
X }
X temp = find_world(argv[1]);
X if (temp == NULL)
X die("%% The world %s is unknown.\n", argv[1]);
X else
X return (temp);
X }
X else if (argc == 3) { /* Port and address specified. */
X temp = (world_rec *) malloc(sizeof(world_rec)); /* Never reclaimed! */
X temp->next = NULL;
X strcpy(temp->world, "World");
X *(temp->character) = '\0';
X *(temp->pass) = '\0';
X if (argv[1][0] == '-') { /* Disable auto login; otherwise */
X disable_auto_login(); /* we might use the default. */
X argv[1]++;
X }
X strcpy(temp->address, argv[1]);
X strcpy(temp->port, argv[2]);
X return (temp);
X }
X else
X die("Usage: %s [world]\n %s address port\n", argv[0], argv[0]);
X
X return (NULL);
X}
END_OF_FILE
if test 3435 -ne `wc -c <'tinywar/fred.c'`; then
echo shar: \"'tinywar/fred.c'\" unpacked with wrong size!
fi
# end of 'tinywar/fred.c'
fi
if test -f 'tinywar/gag.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/gag.c'\"
else
echo shar: Extracting \"'tinywar/gag.c'\" \(7702 characters\)
sed "s/^X//" >'tinywar/gag.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk output special processing: gags and hiliting. */
X/* */
X/* Version 1.0 [ 2/ 2/90] : Created by ABR. */
X/* 1.1 [ 2/ 5/90] : Added whisper gagging. */
X/* 1.2 [ 2/ 5/90] : Minor changes to fix file problems. */
X/* 1.1.4 [5/?/90] : add actions caused by hilite, reg ex */
X/* : matching in full string, not just name */
X/* 1.1.9[6/25/90] : fix hilite action bug. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X
Xextern char *index(), *malloc();
Xextern int comparestr(), nequalstr(), equalstr();
X
Xextern int being_offensive; /* reply to hilites/gags? */
X
Xtypedef struct gag_hilite_entry {
X struct gag_hilite_entry *next, *prev;
X string person; /* person and/or action */
X string action; /* do this if found */
X} gag_hilite_entry;
X
Xgag_hilite_entry *find_person(),*find_person_exact();
X
Xint hilite_other,gag_enabled,acting;
Xstatic gag_hilite_entry *gag_list, *hilite_list, *act_list;
X
Xinit_gagging()
X{
X gag_enabled = TRUE;
X gag_list = NULL;
X init_hilite_utils();
X hilite_other = TRUE;
X hilite_list = NULL;
X act_list = NULL;
X acting = TRUE;
X}
X
Xchar *is_gagged(what)
X char *what;
X{
X register char *place;
X gag_hilite_entry *foundit;
X
X if (!gag_enabled)
X return (0);
X
X if (foundit = find_person(gag_list, what)) { /* Are they gagged? */
X
X return (foundit->action);
X }
X else
X return ((char *) -1);
X}
X
Xchar *should_hilite(what)
X char *what;
X{
X
X gag_hilite_entry *findrec;
X
X if (!hilite_other)
X return ((char *) -1);
X
X if (findrec = find_person(hilite_list, what)) /* Marked for hilite? */
X return (findrec->action);
X else
X return ((char *) -1);
X}
X
Xchar *should_act(what)
X char *what;
X{
X gag_hilite_entry *findrec;
X if (!acting)
X return ((char *) -1);
X if(findrec = find_person(act_list, what))
X return(findrec->action);
X
X return ((char *) -1);
X}
X
Xenable_hiliting()
X{
X hilite_other = TRUE;
X}
Xenable_acting()
X{
X acting = TRUE;
X}
Xdisable_acting()
X{
X acting = FALSE;
X}
X
Xdisable_hiliting()
X{
X hilite_other = FALSE;
X}
X
Xenable_gagging()
X{
X gag_enabled = TRUE;
X}
X
Xdisable_gagging()
X{
X gag_enabled = FALSE;
X}
X
Xdo_add_hilite(who,list)
X char *who;
X gag_hilite_entry **list;
X{
X char *what=0; /* what to do with em? */
X char tempchar;
X char *temp = 0;
X
X if(what = index(who,'=')) { /* is there anyting but a name here? */
X
X register char *temp = what++; /* placeholder */
X
X while(*temp-- == ' '); /* eat all spaces back */
X if(*temp == '\\') *++temp = ' '; /* restore 1 space if necessary */
X tempchar = *temp;
X *temp = 0; /* who is now correct */
X while(*what == ' ') what++; /* eat all spaces forward of = */
X }
X add_person(list, who, what);
X if(temp) *temp = tempchar;
X}
X
Xremove_hilite(who)
X char *who;
X{
X remove_person(&hilite_list, who);
X}
X
Xlist_act(args)
X{
X list_people(act_list,args);
X fprintf(stdout,"%% ** Acting is %sabled.\n",(acting)?"en":"dis");
X}
Xlist_hilite(args)
Xchar *args;
X{
X list_people(hilite_list,args);
X fprintf(stdout,"%% ** Hiliting is %sabled.\n",(hilite_other)?"en":"dis");
X}
X
Xsave_hilite(name)
X char *name;
X{
X save_people("/hilite ", hilite_list, name, "~/tiny.hilite", TRUE);
X}
X
Xremove_gag(who)
X char *who;
X{
X remove_person(&gag_list, who);
X}
X
Xremove_act(who)
X register char *who;
X{
X remove_person(&act_list, who);
X}
X
Xlist_gag(args)
Xchar *args;
X{
X list_people(gag_list,args);
X fprintf(stdout,"%% ** Gagging is %sabled.\n",(gag_enabled)?"en":"dis");
X fflush(stdout);
X}
X
Xsave_gag(name)
X char *name;
X{
X save_people("/gag ", gag_list, name, "~/tiny.gag", FALSE);
X}
X
Xadd_person(list, name, action)
X gag_hilite_entry **list;
X char *name;
X char *action;
X{
X register gag_hilite_entry *new;
X
X if (strlen(name) > MAXSTRLEN) /* Silently truncate long names */
X name[MAXSTRLEN] = '\0';
X
X if ((new = find_person_exact(*list, name)) != NULL) { /* Found, new act. */
X if(action && *action)
X strcpy(new->action, action);
X else
X new->action[0] = 0;
X
X return;
X }
X
X new = (gag_hilite_entry *) malloc(sizeof(struct gag_hilite_entry));
X new->prev = NULL; /* Add at front of list */
X new->next = *list;
X if (new->next != NULL) /* If not at tail of list, */
X new->next->prev = new; /* Set up backlink. */
X *list = new;
X
X strcpy(new->person, name);
X if(action)
X strcpy(new->action, action);
X else
X *new->action = 0;
X}
X
Xvoid nuke_node(where,list)
Xregister gag_hilite_entry *where;
Xgag_hilite_entry **list;
X{
X if (where->prev == NULL) /* Unlink from head */
X *list = where->next;
X else
X where->prev->next = where->next;
X
X if (where->next != NULL) /* If not at end, fix back link */
X where->next->prev = where->prev;
X
X free(where); /* Free allocated storage. */
X}
Xremove_person(list, name)
X gag_hilite_entry **list;
X register char *name;
X{
X register gag_hilite_entry *where;
X
X if (strlen(name) > MAXSTRLEN) /* Silently truncate long names */
X name[MAXSTRLEN] = '\0';
X
X where = find_person_exact(*list, name);
X if (where == NULL) {
X fprintf(stderr, "%% Person %s was not in the list.\n", name);
X return;
X }
X
X nuke_node(where,list);
X}
X
Xgag_hilite_entry *search_list(list, name, function)
X gag_hilite_entry *list;
X register char *name;
X int (*function)();
X{
X register gag_hilite_entry *where;
X
X where = list;
X while ((where) && (function(where->person, name)))
X where = where->next;
X
X return (where);
X}
X
Xgag_hilite_entry *find_person(list, name)
X{
X return search_list(list,name,nequalstr);
X}
X
Xgag_hilite_entry *find_person_exact(list, name)
X{
X return search_list(list,name,comparestr);
X}
Xlist_people(list,match)
X gag_hilite_entry *list;
X char *match;
X{
X register gag_hilite_entry *where;
X
X where = list;
X while (where != NULL) {
X if(!*match)
X fprintf(stdout,"%% %s\n",where->person);
X else
X if(equalstr(match,where->person))
X fprintf(stdout,"%% %s \n::: %s\n", where->person,where->action);
X where = where->next;
X }
X}
X
Xsave_people(cmd, list, name, def, hilite_info) /* Write people to a file. */
X char *cmd;
X gag_hilite_entry *list;
X char *name, *def;
X int hilite_info;
X{
X register FILE *the_file;
X register gag_hilite_entry *where;
X
X if (name[0] == '\0') /* Set default name if none given. */
X strcpy(name, def);
X
X expand_filename(name);
X the_file = fopen(name, "w"); /* Open file */
X if (the_file == NULL) {
X fprintf(stderr,"%% Could not write to %s .\n", name);
X return;
X }
X
X where = list;
X while (where != NULL) { /* Scan linked list, outputting */
X fputs(cmd, the_file); /* a command per person. */
X fputs(where->person, the_file);
X fputs(" = ", the_file);
X fputs(where->action, the_file);
X fputc('\n', the_file);
X where = where->next;
X }
X
X fclose(the_file);
X}
X
Xgag_hilite_entry *purgelist(list,args)
Xgag_hilite_entry **list;
Xchar *args;
X{
X gag_hilite_entry *temp = *list;
X
X while(temp)
X if(equalstr(args,temp->person)) {
X nuke_node(temp,list);
X temp = temp->next;
X }
X else
X temp = temp->next;
X}
X
Xvoid purgegag(args)
Xchar *args;
X{
X if(!*args)
X purgelist(&gag_list,"*");
X else
X purgelist(&gag_list,args);
X}
X
Xvoid purgehilite(args)
Xchar *args;
X{
X
X if(!*args)
X purgelist(&hilite_list,"*");
X else
X purgelist(&hilite_list,args);
X
X}
X
Xvoid purgeact(args)
Xchar *args;
X{
X if(!*args)
X purgelist(&act_list,"*");
X else
X purgelist(&act_list,args);
X}
Xvoid add_gag(args)
Xchar *args;
X{
X do_add_hilite(args,&gag_list);
X}
X
Xvoid add_hilite(args)
Xchar *args;
X{
X do_add_hilite(args,&hilite_list);
X}
X
Xvoid add_act(args)
Xchar *args;
X{
X do_add_hilite(args,&act_list);
X}
END_OF_FILE
if test 7702 -ne `wc -c <'tinywar/gag.c'`; then
echo shar: \"'tinywar/gag.c'\" unpacked with wrong size!
fi
# end of 'tinywar/gag.c'
fi
if test -f 'tinywar/history.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/history.c'\"
else
echo shar: Extracting \"'tinywar/history.c'\" \(8025 characters\)
sed "s/^X//" >'tinywar/history.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include "tl.h"
X
X/* this code is from Andrew T. Molitor(bob) with minor very minor modifications
X * by me (Insane Hermit[Chris Eleveld])
X * Error handling mods, /watchdog, history substitution by you-know-who.
X */
X
X/*
X** Version 1.1.7?8?9 -- Initial implementation.
X** Version 1.2.0b -- /recall is now forward order, add /watchdog
X** Version 1.2.1b -- fix minor bugs, add history substutution
X*/
X#define err(_a) fprintf(stderr,_a) /* maybe do someting usefull later */
X
X#include <strings.h>
X
Xextern char *strstr(),*malloc(),*is_gagged();
Xextern smallstr lastname; /* name of last actor */
Xextern int do_not_save_recall;
X
Xtypedef struct history {
X char *line; /* the actual line that you typed */
X int length;
X struct history *next; /* links for the list... */
X struct history *prev;
X} HISTORY;
X
Xstatic HISTORY *sent_list = 0;
Xstatic HISTORY *sent_position;
Xstatic HISTORY *received_list = 0;
Xstatic HISTORY *received_position;
Xstatic int watchdog_enabled = 1; /* start in watchdog mode */
Xstatic int watchname_enabled = 0; /* start in no watchname mode */
Xstatic int lines_watched = WATCHLINES;
Xstatic int namematches = NAMEMATCHNUM; /* number to match before ignoring */
Xstatic int stringmatches = STRINGMATCHNUM;
X
XHISTORY *do_rewind();
X
Xextern int equalstr();
X
Xint saveline(addline,size,list,position,commandnum)
Xchar *addline;
Xint size;
XHISTORY **list;
XHISTORY **position;
Xint *commandnum;
X{
X HISTORY *new_entry;
X char *line;
X
X if(!size || !(addline[0]))
X return 0;
X if (!(line = malloc((strlen(addline)+1)))) {
X err("malloc error in history");
X return 0;
X }
X
X bcopy(addline, line, size);
X line[size] = 0;
X
X /*
X ** Caution: if commandnum != 0, we assume there is already a valid
X ** list pointed at by position and list, and *commandnum contains
X ** a more-or-less acurate number of commands in the buffer.
X */
X
X if (commandnum && !*commandnum) /* use old when commandnum == 0 */
X {
X register HISTORY *temp = *list;
X
X free((char *) temp->line);
X temp->line = line;
X temp->length = size;
X *list = temp->prev;
X return 1;
X }
X
X /* make new structure */
X
X if(!(new_entry = (HISTORY *) malloc(sizeof(HISTORY)))) {
X err("malloc error in history");
X free((char *) line);
X return 0;
X }
X
X
X new_entry->line = line;
X new_entry->length = size;
X
X if(!*list) /* If the list is empty.. */
X {
X *list = new_entry;
X new_entry->next = new_entry->prev = new_entry;
X *position = new_entry;
X (*commandnum)--;
X }
X else
X { /* list not empty */
X (*commandnum)--;
X new_entry->next = (*list)->next;
X new_entry->prev = *list;
X ((*list)->next)->prev = new_entry;
X (*list)->next = new_entry;
X *position = new_entry;
X }
X return 1;
X}
X/*
X** return last command in history_buffer, re-wind sent_position
X*/
X
Xint recallf(length, line)
X int *length;
X char *line;
X{
X if(!sent_position)
X return;
X sent_position = sent_position->prev;
X bcopy(sent_position->line, line, sent_position->length);
X *length = sent_position->length;
X}
X
X/*
X** return first command in history buffer, advance sent_position
X*/
X
Xint recallb(length, line)
X int *length;
X char *line;
X{
X if(sent_position)
X {
X bcopy(sent_position->line, line, sent_position->length);
X *length = sent_position->length;
X sent_position = sent_position->next;
X }
X}
X/*
X * add a structure containing line to list.
X */
X
Xvoid addhistory(addline,size)
Xchar *addline;
Xint size;
X{
X static int commandnum=SAVECOMMANDS; /* # outgoing lines to save */
X
X if(saveline(addline,size,&sent_list,&sent_position,&commandnum))
X sent_position = sent_list->next;
X}
X
Xvoid addbuffer(line,size)
Xchar *line;
Xint size;
X{
X static int receivednum=SAVERECEIVED; /* # incomming lines to save */
X
X if(saveline(line,size,&received_list,&received_position,&receivednum))
X received_position = received_list->next;
X
X}
X
XHISTORY *do_rewind(number)
Xint *number; /* number of lines to rewind */
X{
X register int count=1;
X
X HISTORY *retptr = received_list;
X if(!retptr)
X return(0);
X retptr = received_list->next; /* I'm drunk. I can't think. */
X while(--(*number) && retptr != received_list) {
X retptr = retptr->next;
X count++;
X }
X *number = count; /* actual number rewound */
X return(retptr);
X}
X
Xvoid do_printbuffer(number,compstr)
Xint number;
Xchar *compstr;
X{
X char *defaultstr = "*"; /* default print all */
X HISTORY *tempbufptr;
X
X if(!compstr)
X compstr = defaultstr;
X if(!number)
X number = 23; /* dump full screen */
X
X if(!(tempbufptr = do_rewind(&number)))
X number = 0;
X
X fprintf(stdout,"----- start buffer recall ------\n");
X
X while(number--)
X {
X if(equalstr(compstr,tempbufptr->line))
X fprintf(stdout,"%s\n",tempbufptr->line);
X
X tempbufptr = tempbufptr->prev;
X
X }
X fprintf(stdout,"----- end buffer recall --------\n");
X fflush(stdout);
X}
X
X/*
X** Function returns 1 if input should be ignored, 0 if input OK.
X*/
X
Xint watchdog(s)
Xchar *s;
X{
X HISTORY *tempbufptr;
X register int namelen;
X int lines = lines_watched,
X nmatches = namematches,
X smatches = stringmatches;
X
X if(!watchdog_enabled && !watchname_enabled)
X return 0;
X
X if(lastname && *lastname)
X namelen = strlen(lastname);
X
X if(!(tempbufptr = do_rewind(&lines)))
X return 0;
X
X while(lines--) {
X if(watchname_enabled && !strncmp(lastname,tempbufptr->line,namelen)
X && !(--nmatches)) {
X char *action;
X action = is_gagged(s);
X if(action != (char *) -1) {
X return 1;
X }
X fprintf(stdout,"%% %s has been overactive lately. Gag? [y/n]\n",lastname);
X fflush(stdout);
X nmatches = getchar(); /* reuse it. */
X if((nmatches == (int) 'y') || (nmatches == (int) 'Y')) {
X strcat(lastname, " *");
X handle_gag_command(lastname);
X lastname[namelen] = 0;
X fprintf(stdout,"%% %s is securely gagged.\n",lastname);
X fflush(stdout);
X return 1; /* ignore */
X }
X }
X if(watchdog_enabled && !strcmp(tempbufptr->line,s) && !(--smatches))
X return 1; /* ignore this */
X
X tempbufptr = tempbufptr->prev;
X }
X return 0;
X}
X
Xannounce_watchdog()
X{
X printf("%% Watchdog is %sabled, watching for %d out of %d lines\n", (watchdog_enabled)?"en":"dis",stringmatches,lines_watched);
X fflush(stdout);
X}
Xannounce_watchname()
X{
X printf("%% Watchname is %sabled, watching for %d of %d lines by the same person.\n",(watchname_enabled)?"en":"dis",namematches,lines_watched);
X}
Xenable_watchdog(args)
Xchar *args;
X{
X int lwatch,lmatch;
X
X if(*args) { /* maybe set new number of lines to watch/match */
X lmatch = atoi(args);
X if(args = index(args,' '))
X lwatch = atoi(++args);
X if(lwatch)
X lines_watched = lwatch;
X if(lmatch)
X stringmatches = lmatch;
X }
X watchdog_enabled = 1;
X announce_watchdog();
X}
Xenable_namewatch(args)
Xchar *args;
X{
X int lwatch,nmatch;
X if(*args) {
X nmatch = atoi(args);
X if(args = index(args,' '))
X lwatch = atoi(++args);
X if(lwatch)
X lines_watched = lwatch;
X if(nmatch)
X namematches = nmatch;
X }
X watchname_enabled = 1;
X announce_watchname();
X}
Xdisable_namewatch()
X{
X watchname_enabled = 0;
X announce_watchname();
X}
Xdisable_watchdog()
X{
X watchdog_enabled = 0;
X announce_watchdog();
X}
X
Xint history_sub(args)
Xchar *args;
X{
X HISTORY *temp_ptr = sent_list;
X char *where,*replace;
X hugestr tempblob;
X
X if(!temp_ptr || !args || !*args)
X return;
X
X if(!(replace = index(args,'^')))
X return; /* nothing to replace with */
X
X *replace++ = 0; /* remember to restore this, match is args. */
X
X do {
X temp_ptr = temp_ptr->next;
X if(where = strstr(temp_ptr->line,args)) { /* found match */
X strncpy(tempblob,temp_ptr->line,(where - temp_ptr->line));
X tempblob[where - temp_ptr->line] = '\0';
X strcat(tempblob,replace);
X strcat(tempblob,(where+strlen(args)));
X do_not_save_recall = TRUE;
X old_process_buffer(tempblob,strlen(tempblob));
X addhistory(tempblob,strlen(tempblob));
X *--replace = '^';
X return;
X }
X } while(temp_ptr != sent_list);
X *--replace = '^';
X}
END_OF_FILE
if test 8025 -ne `wc -c <'tinywar/history.c'`; then
echo shar: \"'tinywar/history.c'\" unpacked with wrong size!
fi
# end of 'tinywar/history.c'
fi
if test -f 'tinywar/keyboard.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/keyboard.c'\"
else
echo shar: Extracting \"'tinywar/keyboard.c'\" \(11212 characters\)
sed "s/^X//" >'tinywar/keyboard.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk keyboard handler. */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* 1.1 [ 1/25/90] : Added minimal termcap support. */
X/* 1.2 [ 1/26/90] : Clean up terminal state on ^C. */
X/* 1.3 [ 2/ 2/90] : Allow interrupts to be ignored. */
X/* Optionally use stty information. */
X/* 1.4 [ 2/ 5/90] : Add minimal command recall. Flush log */
X/* file on suspend. Fix problem with gag */
X/* causing spurious input erasure. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <signal.h>
X#include <sys/ioctl.h>
X#include <sgtty.h>
X#include <errno.h>
X#include <stdio.h>
X
X /* For some odd systems, which don't put this in errno.h. */
X
Xextern int errno;
Xint loop; /* ctrl-c sets this so we get out of long loops */
X
X#undef CTRL
X#define CTRL(x) ('x' & 037)
X
X#ifdef TERMCAP
Xextern char *getenv();
Xstatic int have_clear;
Xstatic char start_of_line[16], clear_to_eol[16]; /* Warning, short! */
Xstatic char write_buffer[64]; /* Also rather short.... */
Xstatic char *write_buffer_ptr;
X#endif
X
Xstatic int keyboard_inited = FALSE; /* Initialized yet? */
X
Xstatic int num_columns; /* Number of columns on terminal. */
Xstatic int current_column; /* Current input column (0->nc). */
Xstatic string keyboard_buffer; /* Buffer for current input. */
Xstatic string recall_buffer; /* Buffer for previous input. */
Xstatic int keyboard_pos; /* Characters entered so far. */
Xstatic int recall_pos; /* Characters on previous input. */
Xstatic int allow_intr; /* Should we quit on INTR? */
Xstatic int recall_pending; /* Flag: recall previous string. */
Xint do_not_save_recall; /* Flag: don't save recall buffer. */
X
Xstatic char k_delete, k_delete_2; /* Backspace character(s). */
Xstatic char k_erase, k_erase_2; /* Erase-line character(s). */
Xstatic char k_word; /* Erase-word character. */
Xstatic char k_refresh; /* Refresh-line character. */
Xstatic char k_recall;
Xstatic char k_recallb;
X
Xextern smallstr ourpasswd;
Xextern int history_sub();
Xextern int getpid();
X/*extern void kill();*/
X
Xextern int runall(); /* tinytalk processes */
X
Xsigint_handler() /* Restore terminal state; cleanup. */
X{
X if (allow_intr)
X {
X register char c; /* input character */
X
X fprintf(stderr,"\nReally exit? [y/n]\n");
X if(((c = getchar()) == 'y') || (c == 'Y'))
X die("\n\nInterrupt, exiting.\n"); /* Exit through error handler. */
X }
X printf("\n");
X loop = 0; /* if now looping then break out */
X}
X
Xvoid sigtstp_handler() /* Leave terminal alone! */
X{
X flush_logfile();
X
X cooked_echo_mode();
X
X killpg(getpid(),SIGSTOP); /* just in case you're running screen */
X cbreak_noecho_mode();
X
X if (keyboard_pos != 0) /* If there is input, we want to */
X set_refresh_pending(); /* refresh when we start back up. */
X}
X
Xpreinit_keyboard()
X{
X allow_interrupts();
X no_use_stty();
X
X do_not_save_recall = FALSE;
X recall_pending = FALSE;
X recall_pos = 0;
X}
X
Xallow_interrupts()
X{
X allow_intr = TRUE;
X}
X
Xdisallow_interrupts()
X{
X allow_intr = FALSE;
X}
X
Xuse_stty()
X{
X struct sgttyb sg_blob;
X struct ltchars lt_blob;
X
X if (ioctl(0, TIOCGETP, &sg_blob) == -1)
X perror("TIOCGETP ioctl");
X if (ioctl(0, TIOCGLTC, &lt_blob) == -1)
X perror("TIOCGLTC ioctl");
X
X k_delete = k_delete_2 = sg_blob.sg_erase;
X k_erase = k_erase_2 = sg_blob.sg_kill;
X
X k_word = lt_blob.t_werasc;
X k_refresh = lt_blob.t_rprntc;
X
X k_recall = '\020';
X k_recallb = CTRL(N);
X}
X
Xno_use_stty()
X{
X k_delete = '\010'; /* Backspace. */
X k_delete_2 = '\177'; /* Delete. */
X
X k_erase = '\025'; /* Control-U. */
X k_erase_2 = '\030'; /* Control-X. */
X
X k_word = '\027'; /* Control-W. */
X
X k_recall = '\020';
X k_recallb = CTRL(N);
X
X k_refresh = '\022'; /* Control-R. */
X}
X
Xinit_keyboard()
X{
X struct winsize size;
X
X cbreak_noecho_mode();
X
X if (ioctl(0, TIOCGWINSZ, &size) == -1)
X perror("TIOCGWINSZ ioctl");
X
X num_columns = size.ws_col;
X if (num_columns <= 20) /* Suspicious, reset it. */
X num_columns = 80;
X set_default_wrap(num_columns);
X
X keyboard_pos = 0; /* No input yet. */
X current_column = 0; /* Left side of screen. */
X
X signal(SIGINT, sigint_handler); /* Control-C. */
X#ifndef DEBUG
X signal(SIGALRM, runall);
X alarm(3);
X#endif
X signal(SIGTSTP, sigtstp_handler); /* Control-Z. */
X#ifdef TERMCAP
X get_termcap_info();
X#endif
X
X keyboard_inited = TRUE;
X}
X
X#ifdef TERMCAP
X
Xget_termcap_info()
X{
X char blob[1024]; /* As per termcap man page */
X char *terminal_name, *temp;
X
X terminal_name = getenv("TERM");
X if (terminal_name == NULL) {
X have_clear = FALSE;
X return;
X }
X
X if (tgetent(blob, terminal_name) == 1) {
X temp = start_of_line;
X if (tgetstr("cr",&temp) == NULL) {
X start_of_line[0] = '\r';
X start_of_line[1] = '\0';
X }
X temp = clear_to_eol;
X if (tgetstr("ce",&temp) == NULL)
X have_clear = FALSE;
X else
X have_clear = TRUE;
X }
X else /* Couldn't read termcap entry */
X have_clear = FALSE;
X}
X
X#endif
X
Xcleanup_keyboard()
X{
X cooked_echo_mode();
X signal(SIGTSTP, NULL);
X}
X
Xhandle_keyboard_input() /* Read input, one char at a time. */
X{
X char ch_noreg;
X register char ch;
X int count;
X
X count = read(0, &ch_noreg, 1); /* Read from stdin. */
X if (count == 0) /* Huh? Ignore this. */
X return;
X
X if (count == -1) {
X if (errno == EWOULDBLOCK)
X return;
X else
X die("%% Couldn't read keyboard.\n");
X }
X
X ch = ch_noreg; /* For stupid compilers. */
X
X if (ch == '\n') {
X write(1, &ch_noreg, 1);
X process_buffer();
X
X if (recall_pending) {
X recall_pending = FALSE;
X
X recallb(&keyboard_pos, keyboard_buffer);
X current_column = keyboard_pos % num_columns;
X
X refresh_entire_buffer();
X }
X else {
X keyboard_pos = 0;
X current_column = 0;
X }
X }
X else {
X if ((ch == k_delete) || (ch == k_delete_2)) /* Backspace. */
X handle_backspace();
X else if ((ch == k_erase) || (ch == k_erase_2)) { /* Cancel line. */
X keyboard_pos = 0;
X
X erase_keyboard_input(TRUE);
X clear_refresh_pending();
X
X current_column = 0;
X }
X else if (ch == k_word) { /* Erase word (back to space). */
X /* This is very, very, VERY ugly. */
X
X handle_backspace(); /* Always delete at least one char. */
X
X while ((keyboard_pos != 0) && (keyboard_buffer[keyboard_pos-1] != ' '))
X handle_backspace();
X }
X else if (ch == k_refresh) { /* Refresh entire input. */
X refresh_entire_buffer();
X }
X else if (ch == k_recall) {
X recallb(&keyboard_pos, keyboard_buffer);
X current_column = keyboard_pos % num_columns;
X refresh_entire_buffer();
X }
X else if (ch == k_recallb) {
X recallf(&keyboard_pos, keyboard_buffer);
X current_column = keyboard_pos % num_columns;
X refresh_entire_buffer();
X }
X else if ((ch < ' ') || (keyboard_pos == MAXSTRLEN - 1)) { /* Beep! */
X write(1, "\007", 1);
X }
X else {
X keyboard_buffer[keyboard_pos++] = ch;
X current_column = (current_column + 1) % num_columns;
X write(1, &ch_noreg, 1);
X }
X }
X}
X
Xhandle_backspace() /* Do a backspace.... */
X{
X if (keyboard_pos != 0) {
X keyboard_pos--;
X
X if (current_column != 0) { /* Can do BS, SPC, BS. */
X write(1, "\010 \010", 3);
X current_column--;
X }
X else {
X current_column = num_columns - 1; /* Wrapped around. */
X do_refresh(); /* Will redraw the right part. */
X }
X }
X}
X
Xold_process_buffer(kbuffer,kpos)
Xchar *kbuffer; /* parts of keyboard_buffer */
Xint kpos; /* position in buffer */
X{
X char savechar;
X
X if (kpos == 0) /* Nothing typed. */
X return;
X
X if (kbuffer[0] == '/') {
X if ((kbuffer[1] == '/') || (kbuffer[1] == '^')) {/* Literal. */
X savechar = kbuffer[kpos];
X if(kbuffer[kpos - 1] != '\n') /* never transmit more than one newline */
X kbuffer[kpos] = '\n';
X else
X kpos--;
X transmit(kbuffer + 1, kpos);
X kbuffer[kpos] = savechar;
X log_input(kbuffer);
X return;
X } else { /* Single slash, it's a command. */
X savechar = kbuffer[kpos];
X kbuffer[kpos] = 0;
X handle_command(kbuffer, FALSE);
X kbuffer[kpos] = savechar;
X log_input(kbuffer); /* Should this be logged? -- ABR */
X }
X }
X else
X if(kbuffer[0] == '^') { /* history substitution, fer sure. */
X savechar = kbuffer[kpos];
X kbuffer[kpos] = 0;
X do_not_save_recall = TRUE;
X history_sub(kbuffer+1);
X kbuffer[kpos] = savechar;
X }
X else {
X if(kbuffer[kpos -1] != '\n') {
X savechar = kbuffer[kpos];
X kbuffer[kpos] = '\n';
X transmit(kbuffer, kpos);
X log_input(kbuffer);
X kbuffer[kpos] = savechar;
X }
X else
X transmit(kbuffer,--kpos);
X }
X}
X
X
Xprocess_buffer()
X{
X int kpos = keyboard_pos;
X char *kbuffer = keyboard_buffer;
X char *temp = kbuffer;
X
X while ((temp = (char *) index(temp,'%'))) {
X if (*(temp+1) == '|') { /* "%|" means start new line */
X old_process_buffer(kbuffer,(char *) temp - (char *) kbuffer);
X temp += 2;
X kpos -= (temp - kbuffer);
X kbuffer = temp;
X }
X else temp++; /* that percent not dangerous */
X }
X old_process_buffer(kbuffer,kpos); /* do it as of old */
X if (!do_not_save_recall)
X addhistory(kbuffer,kpos);
X else
X do_not_save_recall = FALSE;
X}
Xrefresh_entire_buffer() /* Refresh all lines of buffer. */
X{
X register int i;
X
X erase_keyboard_input(TRUE); /* Start at beginning of line. */
X /* Dump full lines. */
X for (i = 0; i <= keyboard_pos - num_columns; i += num_columns) {
X write(1, keyboard_buffer+i, num_columns);
X write(1, "\n", 1);
X }
X
X do_refresh(); /* Handle possibly partial tail. */
X}
X
Xdo_refresh()
X{
X int loc; /* Place to start refresh from */
X int modulo;
X
X modulo = keyboard_pos % num_columns; /* Number on last line */
X loc = keyboard_pos - modulo;
X
X if (modulo != 0)
X write(1, &keyboard_buffer[loc], modulo);
X
X clear_refresh_pending();
X}
X
X#ifdef TERMCAP
Xwrite_one(c)
X char c;
X{
X *(write_buffer_ptr++) = c;
X}
X#endif
X
Xerase_keyboard_input(forced)
X int forced; /* Forced output? */
X{
X if ((!forced) && (current_column == 0))
X return;
X
X#ifdef TERMCAP
X
X if (have_clear) { /* Can we use termcap now? */
X write_buffer_ptr = write_buffer;
X tputs(start_of_line, 1, write_one);
X tputs(clear_to_eol, 1, write_one);
X write(1, write_buffer, write_buffer_ptr - write_buffer);
X goto end_termcap;
X }
X
X /* Drops through into non-TERMCAP code otherwise... */
X
X#endif
X
X {
X int temp;
X string buffer; /* Should be long enough for 80*3. */
X char *ptr;
X
X temp = current_column;
X ptr = buffer;
X
X while (temp != 0) { /* Erase line, backwards. */
X *(ptr++) = '\010';
X *(ptr++) = ' ';
X *(ptr++) = '\010';
X temp--;
X }
X write(1, buffer, ptr - buffer);
X }
X
Xend_termcap:
X
X if (keyboard_pos != 0) /* If there is input, schedule a */
X set_refresh_pending(); /* refresh event. */
X
X}
X
Xavoid_recall()
X{
X do_not_save_recall = TRUE;
X}
X
Xdo_keyboard_recall()
X{
X if (!keyboard_inited) /* Dummy, nothing to recall yet! */
X return;
X
X recall_pending = TRUE;
X do_not_save_recall = TRUE;
X}
END_OF_FILE
if test 11212 -ne `wc -c <'tinywar/keyboard.c'`; then
echo shar: \"'tinywar/keyboard.c'\" unpacked with wrong size!
fi
# end of 'tinywar/keyboard.c'
fi
if test -f 'tinywar/log.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/log.c'\"
else
echo shar: Extracting \"'tinywar/log.c'\" \(1823 characters\)
sed "s/^X//" >'tinywar/log.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk logging. */
X/* */
X/* Version 1.0 [ 1/25/90] : Initial implementation by ABR. */
X/* 1.1 [ 2/ 5/90] : Added explicit file flushing. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X
Xstatic FILE *log_file;
Xstatic string log_file_name;
Xstatic int log_on, log_me;
X
Xinit_logging()
X{
X strcpy(log_file_name, "~/tiny.log"); /* In home directory. */
X expand_filename(log_file_name);
X log_on = 0; /* Don't log output */
X log_me = 0; /* Don't log input either */
X log_file = NULL; /* No log file is open. */
X}
X
Xenable_logging(name) /* Enable logging. Null name means */
X char *name; /* use current default. */
X{
X if (*name != '\0') {
X strcpy(log_file_name, name);
X expand_filename(log_file_name);
X }
X
X if (log_file != NULL) /* Close current log file */
X fclose(log_file);
X
X log_file = fopen(log_file_name, "a"); /* Append to log file */
X log_on = TRUE;
X if (log_file == NULL) {
X fprintf(stderr,"%% Could not open log file %s.\n", log_file_name);
X log_on = FALSE;
X }
X}
X
Xdisable_logging()
X{
X log_on = FALSE; /* Turn off logging */
X if (log_file != NULL) { /* Close file if open */
X fclose(log_file);
X log_file = NULL;
X }
X}
X
Xflush_logfile() /* Flush log file to disk. */
X{
X if (log_file != NULL)
X fflush(log_file);
X}
X
Xenable_logme()
X{
X log_me = TRUE;
X}
X
Xdisable_logme()
X{
X log_me = FALSE;
X}
X
Xlog_output(s) /* From server */
X char *s;
X{
X if (log_on && (log_file != NULL)) {
X fputs(s, log_file);
X fputc('\n', log_file);
X }
X}
X
Xlog_input(s) /* From keyboard */
X char *s;
X{
X if (log_on && log_me && (log_file != NULL)) {
X fputs(s, log_file);
X fputc('\n', log_file);
X }
X}
END_OF_FILE
if test 1823 -ne `wc -c <'tinywar/log.c'`; then
echo shar: \"'tinywar/log.c'\" unpacked with wrong size!
fi
# end of 'tinywar/log.c'
fi
if test -f 'tinywar/macro.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/macro.c'\"
else
echo shar: Extracting \"'tinywar/macro.c'\" \(5387 characters\)
sed "s/^X//" >'tinywar/macro.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk macro handling. */
X/* */
X/* Version 1.0 [ 1/25/90] : Initial implementation by ABR. */
X/* 1.1 [ 1/26/90] : Added support for listing macros. */
X/* 1.2 [ 1/27/90] : Fixed bug in add_macro. */
X/* 1.3 [ 2/ 5/90] : Fixed error message in remove_macro. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X
X#define MAX_ARGS 4 /* Watch out in process_macro */
X /* if you change this. */
X
X#define NAME_LEN 31 /* Size of a macro's name */
Xtypedef char namestr[NAME_LEN+1]; /* Also max arg size; if changed, */
X /* look at process_macro. */
X
Xtypedef struct macro {
X struct macro *next, *prev; /* Linked list of macros */
X namestr the_name;
X char *the_body; /* Dynamically allocated */
X} macro;
X
Xextern char *rindex(),*malloc();
X
Xmacro *find_macro();
Xvoid nuke_macro();
X
Xstatic macro *header;
X
Xinit_macros()
X{
X header = NULL;
X}
X
Xadd_macro(name, body)
X register char *name;
X char *body;
X{
X register macro *new;
X
X if (strlen(name) > NAME_LEN) /* Silently truncate long names */
X name[NAME_LEN] = '\0';
X
X if (find_macro(name) != NULL) {
X fprintf(stderr, "%% Macro %s is already defined.\n", name);
X return;
X }
X
X new = (macro *) malloc(sizeof(struct macro)); /* Allocate space */
X new->prev = NULL; /* Add at front of list */
X new->next = header;
X if (new->next != NULL) /* If not at tail of list, */
X new->next->prev = new; /* Set up backlink. */
X header = new;
X
X strcpy(new->the_name, name);
X new->the_body = malloc(strlen(body) + 1);
X strcpy(new->the_body, body);
X}
X
Xvoid nuke_macro(where)
Xregister macro *where;
X{
X
X if (where->prev == NULL) /* Unlink from head */
X header = where->next;
X else
X where->prev->next = where->next;
X
X if (where->next != NULL) /* If not at end, fix back link */
X where->next->prev = where->prev;
X
X free(where->the_body); /* Free allocated storage. */
X free(where);
X}
Xremove_macro(name) /* Undefine a macro */
X register char *name;
X{
X register macro *where;
X
X if (strlen(name) > NAME_LEN) /* Silently truncate long names */
X name[NAME_LEN] = '\0';
X
X where = find_macro(name);
X if (where == NULL) {
X fprintf(stderr, "%% Macro %s was not defined.\n", name);
X return;
X }
X nuke_macro(where);
X}
X
Xwrite_macros(name) /* Write macros to a file. */
X char *name;
X{
X register FILE *macro_file;
X register macro *where;
X
X expand_filename(name);
X macro_file = fopen(name, "w"); /* Open file */
X if (macro_file == NULL) {
X fprintf(stderr,"%% Could not write macros to %s .\n", name);
X return;
X }
X
X where = header;
X while (where != NULL) { /* Scan linked list, outputting */
X fputs("/def ", macro_file); /* the macros. */
X fputs(where->the_name, macro_file);
X fputs(" = ", macro_file);
X fputs(where->the_body, macro_file);
X fputc('\n', macro_file);
X where = where->next;
X }
X
X fclose(macro_file);
X}
X
Xprocess_macro(name, args, deststr) /* Process a macro invocation. */
X char *name, *args, *deststr; /* Warning: no length checking! */
X{
X register macro *where;
X register char *source, *dest, ch;
X namestr arg_ary[MAX_ARGS];
X int i;
X char *tempchar;
X
X if (strlen(name) > NAME_LEN) /* Silently truncate long names */
X name[NAME_LEN] = '\0';
X
X if(tempchar = rindex(name,'\n'))
X *tempchar = 0;
X
X where = find_macro(name);
X if(tempchar)
X *tempchar = '\n';
X
X if (where == NULL) {
X fprintf(stderr,"%% Macro %s is not defined.\n", name);
X deststr[0] = '\0';
X return;
X }
X
X for (i=0; i<MAX_ARGS; i++) { /* Zero all arguments. */
X arg_ary[i][0] = '\0';
X }
X sscanf(args, "%31s %31s %31s %31s", arg_ary[0], arg_ary[1], arg_ary[2], arg_ary[3]);
X
X source = where->the_body; /* Start copying macro text. */
X dest = deststr;
X
X while (*source != '\0') {
X if (*source != '%') /* If not special char, just copy. */
X *dest++ = *source++;
X else { /* Look at next char. */
X source++;
X ch = *source; /* uppercase ch */
X
X if (ch == '%') {
X *dest++ = '%';
X source++;
X }
X else if (ch == '*') { /* Entire command line. */
X strcpy(dest, args);
X dest += strlen(args);
X source++;
X }
X else if ((ch >= '1') && (ch <= '4')) { /* Argument insertion. */
X strcpy(dest, arg_ary[ch - '1']);
X dest += strlen(arg_ary[ch - '1']);
X source++;
X }
X else { /* Don't know what it was. Guess %. */
X *dest++ = '%'; /* Don't advance source here. */
X }
X }
X }
X
X *dest++ = '\n'; /* Add a newline. */
X *dest = '\0'; /* Terminate the expansion. */
X}
X
Xmacro *find_macro(name)
X register char *name;
X{
X register macro *where;
X
X where = header;
X while ((where != NULL) && (!equalstr(where->the_name, name)))
X where = where->next;
X
X return (where);
X}
X
Xlist_all_macros(match)
X char *match;
X{
X register macro *where;
X
X where = header;
X while (where != NULL) {
X if (match) {
X if(equalstr(match,where->the_name))
X printf("%% %s = %s\n", where->the_name, where->the_body);
X }
X else
X printf("%% %s\n", where->the_name);
X where = where->next;
X }
X}
X
Xvoid purgemacro(args)
Xchar *args;
X{
X register macro *list = header;
X register char *match = "*";
X
X if(*args)
X match = args;
X
X while(list) {
X if(equalstr(match,list->the_name))
X nuke_macro(list);
X list = list->next;
X }
X
X}
END_OF_FILE
if test 5387 -ne `wc -c <'tinywar/macro.c'`; then
echo shar: \"'tinywar/macro.c'\" unpacked with wrong size!
fi
# end of 'tinywar/macro.c'
fi
if test -f 'tinywar/process.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/process.c'\"
else
echo shar: Extracting \"'tinywar/process.c'\" \(5586 characters\)
sed "s/^X//" >'tinywar/process.c' <<'END_OF_FILE'
X/*
X** Tinytalk processes by LKP.
X** [dawn of time] - idea and first /repeat implementation
X** [ 6/26/90 ] - hacked in /do_quote handling, if
X** DEBUG fire runall() after select(),
X** otherwise use alarm(1)
X** [ 6/27/90 ] - fix do_kill() infinite loop, add
X** support to not log /repeat and /quote
X*/
X#include <stdio.h>
X#include "tp.h"
X
Xextern char *index();
Xextern int newproc();
Xextern int do_quote();
Xextern void runlist();
X
Xmedstr line;
Xextern int do_not_save_recall;
X
X#define err(_a) fprintf(stderr,_a);
X
XTPROC *proclist=0; /* procedures to execute */
X
Xextern char *rindex();
Xvoid do_ps(args)
X{
X TPROC *tprocptr = proclist;
X#ifndef DEBUG
X alarm(0);
X#endif
X while(tprocptr) {
X fprintf(stdout,"[%3d] %s",tprocptr->pid,tprocptr->args);
X tprocptr = tprocptr->next;
X }
X fflush(stdout);
X#ifndef DEBUG
X alarm(1);
X#endif
X}
Xint newproc(count,funct,args,arglen,fp,fname)
Xint count;
Xint (*funct)();
Xchar *args;
Xint arglen;
XFILE *fp;
Xchar *fname;
X{
X TPROC *proc;
X static int pid = 0;
X
X if(!(proc = (TPROC *) malloc((unsigned) sizeof(TPROC)))) {
X err("out of memory in newproc");
X return -1;
X }
X
X if(!(proc->args = (char *) malloc((unsigned) arglen))) {
X err("out of memory in newproc");
X free((char *) proc);
X return -1;
X }
X
X#ifndef DEBUG
X alarm(0);
X#endif
X proc->count = count; /* for /repeat. -1 for /quote */
X proc->funct = funct;
X strcpy(proc->args,args);
X strcpy(proc->fname,fname);
X proc->arglen = arglen;
X proc->pid = ++pid;
X proc->fp = fp; /* for /quote and /command. -1 for /repeat */
X
X proc->next = proclist; /* put at head of list */
X if(proclist) /* already a list */
X proc->last = proclist->last;
X else
X proc->last = 0;
X
X proclist = proc; /* new head of list */
X
X#ifndef DEBUG
X alarm(1);
X#endif
X return(pid); /* so the pid generator fucks up at 32K. big deal */
X}
X
Xint nukeproc(proc)
XTPROC *proc;
X{
X#ifndef DEBUG
X alarm(0);
X#endif
X
X if(proc == proclist)
X proclist = proc->next;
X
X if(proc->last)
X (proc->last)->next = proc->next;
X
X if(proc->next)
X (proc->next)->last = proc->last;
X
X free((char *) proc->args);
X free((char *) proc);
X#ifndef DEBUG
X alarm(1);
X#endif
X
X}
X
Xint do_kill(pid)
X{
X register TPROC *temp = proclist;
X
X#ifndef DEBUG
X alarm(0);
X#endif
X while(temp && (temp->pid != pid))
X temp = temp->next;
X
X if(temp)
X nukeproc(temp);
X else
X err("no such process\n");
X#ifndef DEBUG
X alarm(1);
X#endif
X}
X
Xvoid runall()
X{
X TPROC *current=proclist;
X
X while(current) {
X runproc(current);
X current = current->next;
X }
X#ifndef DEBUG
X alarm(1);
X#endif
X}
X
Xint runproc(proc)
XTPROC *proc;
X{
X if(!(proc->count)) { /* don't run this again if count == 0 */
X nukeproc(proc);
X return 0;
X }
X
X (*proc->funct)(proc); /* run it */
X
X}
X
Xint do_repeat(proc)
XTPROC *proc;
X{
X if(proc->count--) {
X register int old_recall_stat;
X
X do_not_save_recall = 1;
X old_process_buffer(proc->args,proc->arglen);
X do_not_save_recall = old_recall_stat;
X }
X else
X nukeproc(proc);
X}
X
Xint do_quote(proc)
XTPROC *proc;
X{
X string buffer; /* output buffer */
X register char *temp;
X register int old_recall_stat;
X char inputline[132]; /* what fgets uses */
X
X
X if(!(fgets(inputline,132,proc->fp))) { /* file ends */
X close(proc->fp);
X if(!strncmp(proc->fname,".ttemp",6)) { /* it's a temp file */
X sprintf(buffer,"rm %s",proc->fname);
X system(buffer);
X }
X nukeproc(proc);
X return;
X }
X
X if(temp = rindex(inputline,'\n'))
X *temp = 0;
X sprintf(buffer,proc->args,inputline);
X old_recall_stat = do_not_save_recall;
X do_not_save_recall = 1;
X old_process_buffer(buffer,strlen(buffer));
X do_not_save_recall = old_recall_stat;
X}
X
X
X
Xchar *restof(temp)
Xchar *temp;
X{
X static medstr fname; /* return file name */
X char *kludge = fname; /* stupid compiler. */
X
X strcat(line,"%s"); /* filename to be replaced by it's contents */
X
X if(*++temp != '"') /* rest of temp is file name */
X strcpy(kludge,temp);
X else
X while(*++temp) {
X
X if(*temp == '\\') {
X *kludge++ = *++temp;
X }
X else
X if(*temp == '"') { /* end of file name */
X char *temptr = ++temp;
X
X *kludge = 0; /* just in case */
X
X while((temptr = index(temptr,'\\'))) /* don't care about literals */
X strcpy(temptr,(temptr+1));
X
X strcat(line,temp);
X return fname;
X }
X else
X *kludge++ = *temp;
X }
X
X /*
X ** NOTE! If no matching '"' found above, assume it's preset after
X ** the very last character!
X */
X
X return fname;
X}
X
Xint send_quote(args)
Xchar *args;
X{
X char *temp = args;
X short flag = -1; /* 0 = file quote, 1 = command quote, -1 = error */
X char *kludge;
X char *fname; /* file name/args */
X FILE *fp; /* file pointer */
X
X kludge = line;
X
X while(*temp) {
X if(*temp == '\\') {
X *kludge++ = *++temp;
X *temp++;
X }
X else
X if(*temp == '\'' || *temp == '!') { /* file name follows */
X
X flag = (*temp == '!') ? 1 : 0; /* file quote */
X *kludge = 0; /* for strcat */
X fname = restof(temp); /* restof modifies line */
X break;
X }
X else *kludge++ = *temp++;
X }
X
X if(flag == 1) { /* command quote */
X static int tcount = 0; /* number of tempfiles */
X char tempfile[15]; /* name of temporary file */
X
X sprintf(tempfile,"%s%d%d",".ttemp",getpid(),tcount++);
X sprintf(fname,"%s > %s",fname,tempfile);
X system(fname);
X strcpy(fname,tempfile);
X }
X if(flag != -1) {
X if(!(fp = fopen(fname,"r"))) {
X err("file not found.\n");
X return -1;
X }
X if(!index(line,'\n'))
X strcat(line,"\n");
X newproc(-1,do_quote,line,strlen(line),fp,fname);
X }
X return flag;
X}
X
X
END_OF_FILE
if test 5586 -ne `wc -c <'tinywar/process.c'`; then
echo shar: \"'tinywar/process.c'\" unpacked with wrong size!
fi
# end of 'tinywar/process.c'
fi
if test -f 'tinywar/random.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/random.c'\"
else
echo shar: Extracting \"'tinywar/random.c'\" \(760 characters\)
sed "s/^X//" >'tinywar/random.c' <<'END_OF_FILE'
X/*
X**
X** random.c
X**
X** execute a randomly selected command. entire string is used, sorry.
X**
X*/
X
X#include "tl.h"
X#include <strings.h>
X
X
Xhandle_random_command(args)
Xchar *args;
X{
X unsigned int i=0,j;
X string s;
X char *p;
X
X
X do {
X p=index(args,'|');
X j=random();
X i++;
X if (!(j%i)) {
X if (p)
X j=p-args;
X else
X j=strlen(args);
X strncpy(s,args,j);
X s[j]='\0';
X }
X args=p+1;
X } while (p);
X
X old_process_buffer(s,strlen(s));
X}
X/* you should change handle_input to transmit, or maybe to
X old_process_buffer(s,strlen(s)) [which is what handle_input is for me]
X then make the appropriate changes to the list of commands. Documentation:
X
X /random list-of-items-to-randomize-among separated by '|'
X*/
END_OF_FILE
if test 760 -ne `wc -c <'tinywar/random.c'`; then
echo shar: \"'tinywar/random.c'\" unpacked with wrong size!
fi
# end of 'tinywar/random.c'
fi
if test -f 'tinywar/special.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/special.c'\"
else
echo shar: Extracting \"'tinywar/special.c'\" \(4861 characters\)
sed "s/^X//" >'tinywar/special.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk output special processing. */
X/* */
X/* Version 1.0 [ 2/ 2/90] : Extracted from main loop module; added */
X/* new features for release 1.1. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X
Xextern int bomf; /* are we bomfing around? */
Xextern int loop; /* break out of endless loops */
Xextern int being_offensive; /* reply to others? */
X
Xextern char *index();
Xextern char *should_hilite(),*is_gagged();
Xextern world_rec *find_world();
X
X#define MAX_QUIET 25 /* Max lines to quiet during login. */
X#define MAX_BEEPS 5 /* Be reasonable! Note--you must */
X /* change do_beep() if this is */
X /* increased. */
X
X
Xstatic int quiet_mode; /* Suppress login messages? */
Xstatic int quiet_waiting; /* Are we in a login process? */
Xstatic int quiet_counter; /* So quietness eventually goes off. */
Xstatic int beep_count; /* How many times should we beep? */
Xsmallstr lastname; /* person who last acted */
X
Xset_quiet()
X{
X quiet_mode = TRUE;
X}
X
Xclear_quiet()
X{
X quiet_mode = FALSE;
X quiet_waiting = FALSE; /* Need to initialize this, too. */
X}
X
Xstart_quiet()
X{
X if (quiet_mode) {
X quiet_waiting = TRUE;
X quiet_counter = 0;
X }
X}
X
Xstop_quiet()
X{
X quiet_waiting = FALSE;
X}
X
Xint keep_quiet(what) /* Returns 1 if should suppress. */
X char *what;
X{
X if (!strncmp(what, "Use the WHO command", 19)) {
X quiet_waiting = FALSE; /* No longer waiting. */
X return (1); /* Suppress this line. */
X }
X
X quiet_counter++; /* Don't stay quiet forever, even */
X if (quiet_counter > MAX_QUIET) { /* if we never see the right string. */
X quiet_waiting = FALSE;
X return (0);
X }
X else
X return (1);
X}
X
X /* Quiet logins are also handled here. */
X
Xint special_hook(what) /* Check for special thingies. */
X register char *what;
X{
X char *action;
X
X if (quiet_waiting && keep_quiet(what))
X return (1);
X
X if(watchdog(what))
X return(1);
X /* first off copy this into recall buffer */
X
X addbuffer(what,strlen(what));
X
X /* if (equalstr(what, "#### Please reconnect to*")) /* Portal?
X return (handle_portal(what)); */
X
X extract_first_word(what, lastname); /* Get first word (speaker). */
X
X if (((action = (char *) should_hilite(what))) != ((char *) -1)) {/* Check for hiliting. */
X hilite_on();
X print_with_wrap(what);
X hilite_off();
X if(being_offensive && action) {
X old_process_buffer(action,strlen(action));
X }
X return (1);
X }
X if((action = (char *) should_act(what)) != (char *) -1) {
X old_process_buffer(action,strlen(action));
X return 0;
X }
X if((action = (char *) is_gagged(what)) != (char *) (-1)) { /* Check for gagging. */
X
X if(being_offensive && action) {
X old_process_buffer(action,strlen(action));
X }
X return (1);
X }
X
X return (0); /* Otherwise, just pass it through. */
X}
X
Xextract_first_word(what, str)
X char *what, *str;
X{
X register char *place, save;
X
X if((place = index(what, ' ')) || (place = index(what, '('))) {
X save = *place;
X *place = '\0';
X }
X
X strncpy(str, what, SMALLSTR); /* Extract the name. */
X str[SMALLSTR] = '\0';
X
X if (place != NULL) /* Restore killed character. */
X *place = save;
X}
X
X /* Handle portals. */
X /* Format is: ... to WORLD@IP-addr (hostname) port ??? #### */
X
Xint handle_portal(what)
X char *what;
X{
X string world, address, port, temp;
X int count;
X char *place, ch;
X register world_rec *where;
X
X count = sscanf(what, "#### Please reconnect to %s %s port %s ####",
X world, address, port);
X if (!bomf || (count != 3))
X return (0); /* Invalid format. */
X
X place = index(world, '@'); /* Strip off IP address. */
X *place = '\0';
X
X ch = *(place+1);
X if ((ch >= '0') && (ch <= '9')) /* Use IP address if known. */
X strcpy(address, place+1); /* May not have nameservice--use IP. */
X else {
X strcpy(temp, address+1); /* Strip parens. */
X strcpy(address, temp);
X address[strlen(address)-1] = '\0';
X }
X
X where = find_world(world); /* See if we know about it. */
X if (where == NULL) { /* Nope, build a new one instead. */
X where = (world_rec *) malloc(sizeof(world_rec)); /* Never reclaimed! */
X where->next = NULL;
X strcpy(where->world, world);
X *(where->character) = '\0';
X *(where->pass) = '\0';
X strcpy(where->address, address);
X strcpy(where->port, port);
X }
X
X if (connect_to(where))
X magic_login();
X else
X fprintf(stderr,"%% Connection through portal failed.\n");
X
X return (1); /* Yes, it was a portal. */
X}
X
Xinit_beep()
X{
X beep_count = 0;
X}
X
Xdo_beep()
X{
X if (beep_count != 0)
X write(1, "\007\007\007\007\007", beep_count);
X}
X
Xset_beep(n)
X int n;
X{
X if (n > MAX_BEEPS)
X beep_count = MAX_BEEPS;
X else
X beep_count = n;
X}
X
END_OF_FILE
if test 4861 -ne `wc -c <'tinywar/special.c'`; then
echo shar: \"'tinywar/special.c'\" unpacked with wrong size!
fi
# end of 'tinywar/special.c'
fi
if test -f 'tinywar/stuff.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/stuff.c'\"
else
echo shar: Extracting \"'tinywar/stuff.c'\" \(9667 characters\)
sed "s/^X//" >'tinywar/stuff.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk: the real good stuff (network connections, main loop). */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* 1.1 [ 1/25/90] : Changed for systems without FD_SET. */
X/* 1.2 [ 1/26/90] : Added "quiet" and "nologin" control. */
X/* 1.3 [ 1/27/90] : Increased max number of 'quiet' lines. */
X/* 1.4 [ 2/ 2/90] : Moved out special output handling. */
X/* Changed connection processing. */
X/* 1.5 [ 2/ 5/90] : Modify to handle switching MUDs more */
X/* cleanly. Fix gag problem. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <sys/types.h>
X#include <sys/time.h>
X#include <sys/socket.h>
X#include <netdb.h>
X#include <netinet/in.h>
X#include <fcntl.h>
X#include <sys/errno.h>
X#include <stdio.h>
X
X /* For some odd systems, which don't put this in errno.h. */
X
Xextern int errno;
Xextern int lpmud;
X
X /* For BSD 4.2 systems. */
X
X#ifndef FD_ZERO
X#define DESCR_MASK int
X#define FD_ZERO(p) (*p = 0)
X#define FD_SET(n,p) (*p |= (1<<(n)))
X#define FD_ISSET(n,p) (*p & (1<<(n)))
X#else
X#define DESCR_MASK fd_set /* For BSD 4.3 systems. */
X#endif
X
X /* End of BSD 4.2 systems. */
X
X#define REFRESH_TIME 500000 /* Microseconds */
X#define MAXKLUGE 10 /* times to kluge around send failure */
X
Xextern char *index(), *malloc();
Xextern struct hostent *gethostbyname();
Xextern unsigned long inet_addr();
Xextern world_rec *find_world();
Xextern smallstr lastname; /* last actor */
X
Xextern void runall(); /* ttalk process */
X
Xstatic world_rec *current_world;
Xstatic int current_socket;
Xstatic int connected; /* Are we connected anywhere? */
Xhugestr current_output; /* Queued as messages arrive. */
Xstatic int need_refresh; /* Does input line need refresh? */
Xstatic int done; /* Are we all done? */
Xstatic int use_magic_login; /* Auto-logins enabled? */
Xstatic int flush_pending_output; /* For portals. */
X
Xdo_login(args)
Xchar *args;
X{
X world_rec *to_world; /* this is DUMB! */
X
X strcpy(to_world->world,"bomf world");
X
X sscanf(args,"%s %s %s %s",to_world->address,to_world->port,to_world->character,to_world->pass);
X
X if(!connect_to(to_world))
X printf("%% No dice.\n");
X
X}
X
Xdo_stuff(initial_world)
X world_rec *initial_world;
X{
X int count;
X DESCR_MASK readers, exceptions;
X struct timeval refresh_timeout;
X struct timeval *tv;
X
X flush_pending_output = FALSE;
X
X connected = FALSE;
X if (!connect_to(initial_world))
X die("%% Couldn't connect to initial world.\n");
X
X *current_output = '\0'; /* No output yet. */
X
X done = FALSE;
X
X need_refresh = 0; /* No keyboard typing yet. */
X
X magic_login(); /* Log us in, if possible. */
X
X do {
X flush_pending_output = FALSE; /* No output is pending, ignore any */
X /* attempts to flush it. */
X
X FD_ZERO(&readers);
X FD_ZERO(&exceptions);
X FD_SET(0, &readers); /* Check standard input. */
X FD_SET(current_socket, &readers); /* Check socket. */
X
X if (need_refresh) {
X refresh_timeout.tv_sec = 0;
X refresh_timeout.tv_usec = REFRESH_TIME;
X tv = &refresh_timeout;
X }
X else
X tv = NULL;
X
X count = select(current_socket + 1, &readers, NULL, &exceptions, tv);
X
X
X if (count == -1) {
X if (errno != EINTR) /* Control-Z will do this. */
X perror("select");
X }
X else if (count == 0)
X do_refresh();
X else {
X if (FD_ISSET(current_socket, &readers)) {
X handle_socket_input();
X }
X else if (FD_ISSET(0, &readers)) {
X if (need_refresh)
X do_refresh();
X handle_keyboard_input();
X }
X else
X fprintf(stderr,"%% ??select??");
X }
X#ifdef DEBUG
X runall();
X#endif
X if(lpmud)
X runall();
X } while (!done);
X
X disconnect();
X cleanup_keyboard();
X}
X
Xint connect_to(w) /* Try to make a connection. */
X register world_rec *w;
X{
X struct in_addr host_address;
X struct sockaddr_in socket_address;
X int err;
X
X register world_rec *temp_world; /* Use temporaries until we know */
X register int temp_socket; /* that we've succeeded! */
X
X temp_world = w;
X if (!get_host_address(w->address, &host_address)) { /* Can't do it. */
X return(0);
X }
X
X socket_address.sin_family = AF_INET;
X socket_address.sin_port = htons(atoi(w->port));
X bcopy(&host_address, &socket_address.sin_addr, sizeof(struct in_addr));
X
X temp_socket = socket(AF_INET, SOCK_STREAM, 0);
X if (temp_socket < 0) {
X perror("% Couldn't open socket");
X return(0);
X }
X
X#ifndef DEBUG
X alarm(0);
X#endif
X err = connect(temp_socket, &socket_address, sizeof(struct sockaddr_in));
X#ifndef DEBUG
X alarm(1);
X#endif
X if (err < 0) {
X perror("% Couldn't connect to socket");
X return(0);
X }
X
X/* fcntl(temp_socket, F_SETFL, FNDELAY); Do we need this? */
X
X if (connected) /* Disconnect from any open world. */
X disconnect();
X
X current_world = temp_world;
X current_socket = temp_socket;
X
X connected = TRUE;
X return(1); /* Success! */
X}
X
Xint get_host_address(name, addr) /* Get a host address. */
X register char *name;
X register struct in_addr *addr;
X{
X struct hostent *blob;
X union { /* %#@!%!@%#!@ idiot who designed */
X long signed_thingy; /* the inetaddr routine.... */
X unsigned long unsigned_thingy;
X } thingy;
X
X if (*name == '\0') {
X fprintf(stderr, "%% No host address specified.\n");
X return (0);
X }
X
X if ((*name >= '0') && (*name <= '9')) { /* IP address. */
X addr->s_addr = inet_addr(name);
X thingy.unsigned_thingy = addr->s_addr;
X if (thingy.signed_thingy == -1) {
X fprintf(stderr, "%% Couldn't find host %s .\n", name);
X return (0);
X }
X }
X else { /* Host name. */
X blob = gethostbyname(name);
X
X if (blob == NULL) {
X fprintf(stderr, "%% Couldn't find host %s .\n", name);
X return (0);
X }
X
X bcopy(blob->h_addr, addr, sizeof(struct in_addr));
X }
X
X return (1); /* Success. */
X}
X
Xdisconnect() /* Disconnect from current world. */
X{
X if (connected) {
X flush_pending_output = TRUE; /* Flush pending output. This is */
X current_output[0] = '\0'; /* used when switching worlds. */
X close(current_socket);
X }
X
X connected = FALSE;
X}
X
Xold_transmit(s, l) /* Send a message over the socket. */
X char *s;
X int l;
X{
X register int err;
X
X err = send(current_socket, s, l, 0);
X if (err == -1) {
X
X register int send_tries = MAXKLUGE;
X
X while(send_tries-- && (-1 == (err = send(current_socket,s,l,0))));
X
X if(err == -1)
X perror("send");
X }
X}
X
Xtransmit(s,l)
X char *s;
X int l;
X{
X char *temp = s;/* walking pointer */
X hugestr transmitbuffer; /* transmit buffers built here */
X register char *bufptr = transmitbuffer;
X
X while((temp - s) <= l) {
X if(*temp == '%') { /* possible substitution */
X if(*++temp == '%') /* literal */
X *bufptr++ = *temp++;
X else
X if(*temp == 'n' || *temp == 'N') { /* name substitution */
X *temp++;
X strcpy(bufptr,lastname);
X bufptr += strlen(lastname);
X }
X else
X if(*temp == ';' || *temp == '\\') { /* newline substitution */
X *bufptr++ = '\n';
X *bufptr = 0;
X old_transmit(transmitbuffer,strlen(transmitbuffer));
X old_process_buffer(++temp,(l -(temp - s)));
X return;
X }
X else /* dunno. Assume % */
X *bufptr++ = '%';
X }
X else /* normal character */
X *bufptr++ = *temp++;
X }
X *bufptr = 0;
X old_transmit(transmitbuffer,strlen(transmitbuffer));
X}
Xreceive(s)
X register char *s;
X{
X register int count;
X
X count = recv(current_socket, s, MAXSTRLEN, 0);
X if (count == -1) {
X if (errno == EWOULDBLOCK)
X s[0] = '\0';
X else {
X perror("recv failed");
X }
X }
X else
X s[count] = '\0';
X
X if (count <= 0) /* Don't ask me. */
X done = TRUE;
X}
X
Xmagic_login()
X{
X string s;
X register world_rec *def;
X
X if (!use_magic_login) /* Check if auto-login is enabled. */
X return;
X
X if (*(current_world->character) == '\0') { /* Try default world. */
X def = find_world("default");
X/* if (def == NULL) {
X transmit("\n", 1);
X return;
X }
X*/
X if(def) {
X sprintf(s,"\nconnect %s %s\n", def->character, def->pass);
X transmit(s, strlen(s));
X start_quiet(); /* Suppress login messages? */
X return;
X }
X }
X else {
X sprintf(s,"\nconnect %s %s\n", current_world->character,
X current_world->pass);
X transmit(s, strlen(s));
X start_quiet(); /* Suppress login message? */
X return;
X }
X}
X
Xclear_refresh_pending()
X{
X need_refresh = 0;
X}
X
Xset_refresh_pending()
X{
X need_refresh = 1;
X}
X
Xhandle_socket_input()
X{
X string blob;
X hugestr bigblob;
X register char *place;
X
X receive(blob);
X strcat(current_output, blob); /* Concatenate this bunch of input. */
X
X place = index(current_output, '\n'); /* Output any whole lines. */
X if (place != NULL) {
X while (place != NULL) {
X *place = NULL;
X if (!special_hook(current_output))
X print_with_wrap(current_output);
X if (flush_pending_output) { /* Flush the buffer. */
X flush_pending_output = FALSE;
X *current_output = '\0';
X return;
X }
X strcpy(bigblob, place + 1); /* Rest of buffer. */
X strcpy(current_output, bigblob); /* Copy it back to buffer. */
X place = index(current_output, '\n');
X }
X }
X else if(lpmud) { /* kludge. */
X write(1,current_output,strlen(current_output));
X *current_output = '\0';
X }
X if (strlen(current_output) > MAXSTRLEN) { /* Too long, flush it. */
X print_with_wrap(current_output);
X *current_output = '\0'; /* Flush the buffer. */
X }
X}
X
Xenable_auto_login()
X{
X use_magic_login = TRUE;
X}
X
Xdisable_auto_login()
X{
X use_magic_login = FALSE;
X}
X
Xset_done() /* Used by /QUIT command to exit */
X{ /* cleanly. */
X done = TRUE;
X}
END_OF_FILE
if test 9667 -ne `wc -c <'tinywar/stuff.c'`; then
echo shar: \"'tinywar/stuff.c'\" unpacked with wrong size!
fi
# end of 'tinywar/stuff.c'
fi
if test -f 'tinywar/tinytalk.doc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/tinytalk.doc'\"
else
echo shar: Extracting \"'tinywar/tinytalk.doc'\" \(16985 characters\)
sed "s/^X//" >'tinywar/tinytalk.doc' <<'END_OF_FILE'
X
X
X TinyTalk, V1.1
X Anton Rang
X ================
X
XWhat is TinyTalk?
X-----------------
X
X TinyTalk is an interface to the TinyMUD system. It replaces telnet,
Xand adds many new features. Its features include:
X
X * TinyTalk can wrap words at the end of a line.
X
X * TinyTalk can automatically log into your characters.
X
X * TinyTalk can record a TinyMUD session to a file.
X
X * TinyTalk keeps your typing and TinyMUD output from being
X intermingled.
X
X * TinyTalk allows input lines to be up to 512 characters long.
X This allows long descriptions to be entered.
X
X * TinyTalk supports simple macros.
X
X * TinyTalk supports "portals", special exits which connect between
X the various TinyMUD systems. There are also commands which allow
X manually switching systems.
X
X * TinyTalk can hilite pages and whispers, on terminals which support
X boldface or inverse characters.
X
XWho wrote TinyTalk? What is its status?
X----------------------------------------
X
X TinyTalk was written entirely by Anton Rang. He can be reached via
XE-mail, at "ra...@cs.wisc.edu". TinyTalk is semi-supported; bugs will
Xbe fixed, and new features may be incorporated into new versions.
XMail any comments or questions to Anton.
X
X Stewart Clamen (aka "Stewy") came up with the idea for portals, and
Xadded support for them into the GNU Emacs-based client (tinymud.el).
XThe first free-standing program that I know of which implemented them
Xwas written by Russ Smith (aka "Nightfall"). They may be reached at
Xthe addresses "cla...@cs.cmu.edu" and "ru...@uokmax.ecn.uoknor.edu".
X
X Thanks also go to my many beta testers, too numerous to name here.
XThey've been most helpful in finding bugs and suggesting new and
Xuseful features.
X
X TinyTalk is in the public domain. Feel free to make improvements,
Xor take parts of the code for your own programs. I ask only two
Xthings (these aren't legal obligations, just requests):
X
X * If you make changes to TinyTalk, change the version number.
X Don't increment it (i.e. to 1.2 or 2.0); add something to the
X end of the current version number. For instance, you could
X use your initials: TinyTalk 1.1/abr-1. This way, no two
X versions of TinyTalk are likely to have the same version number.
X
X * If you distribute modified versions of TinyTalk, please leave a
X pointer to derby.cs.wisc.edu (128.105.2.162) where the original
X code may be FTPed from.
X
X If you have a minor improvement in mind, it may be best just to send
Xme a mail message. I can incorporate it into the next version.
X
XInstalling TinyTalk.
X--------------------
X
X This is described in the separate README file which you should have
Xreceived with this file. If you have not received it, you can FTP a
Xcopy from derby.cs.wisc.edu (128.105.2.162). It is in the directory
X~ftp/pub/tinytalk.
X
XStarting Tinytalk.
X------------------
X
X Before using TinyTalk for the first time, you may want to create a
Xconfiguration file (described below). TinyTalk will run without one,
Xbut automatic logins and world recognition will not be available. If
Xyou do not have a configuration file, a host name and port number must
Xbe specified, as with 'telnet'. Configuration files are described in
Xa later section.
X
X The simplest way to invoke TinyTalk is simply by typing its name,
Xwithout any arguments. If a configuration file exists, this will read
Xit and connect to the first world in the file. To connect to that
Xworld without logging in, the single argument '-' should be given.
X
X tinytalk Connects to the default world and attempts login.
X tinytalk - Connects to the default world without logging in.
X
X To connect to an alternate world which is in the configuration file,
Xthe name of that world may be given as an argument. A leading '-'
Xindicates that auto-login should be disabled.
X
X tinytalk TinyHELL Connects to the world TinyHELL.
X tinytalk -TinyHELL Connnects to TinyHELL without logging in.
X
X To use TinyTalk without a configuration file, or to connect to a
Xworld which is not in the configuration file, the host name (or
XInternet address) and port number must be given, as with 'telnet'. If
Xa default character exists in the configuration file, auto-login will
Xbe attempted; a leading '-' on the host suppresses this.
X
X tinytalk 192.35.96.111 6250 Connects to TinyHELL.
X tinytalk -uokmax.ecn.uoknor.edu 6250 Connects to TinyHELL, no login.
X
XUsing TinyTalk.
X---------------
X
X TinyTalk works almost the same as a regular telnet interface would.
XOutput from TinyMUD is displayed on the screen. To send a line to
XTinyMUD, just type the line and press return. The most noticeable
Xdifference is that the line you are typing will usually not be mixed
Xin with the output. (The exception is when an input line wraps
Xaround, in which case any entire lines typed so far will remain on the
Xscreen, above output from TinyMUD.)
X
X Commands may be given to TinyTalk by entering a line which begins
Xwith a slash (/). To send a line which begins with a slash to
XTinyMUD, you must start the line with two slashes. (For instance,
Xtyping '//house' would send the line '/house' to TinyMUD. Typing only
X'/house' would cause TinyTalk to look for a 'house' command.)
X
X When you walk through a portal to another TinyMUD, TinyTalk will try
Xto automatically reconnect you to the new system. If the world is
Xdefined in your configuration file (and auto-login has not been
Xdisabled), it will automatically connect you to your character there.
X
X The backspace and delete keys function as usual; in addition,
Xcontrol-U or control-X will erase the entire input line. Control-R
Xwill refresh the current input (which may span multiple lines).
XControl-W will erase the last word typed. (Note: all of these
Xcharacters may be changed, using /stty mode.)
X
X Control-C (or the interrupt character) will exit TinyTalk (unless
Xthe /nointr command is used); it's recommended that the standard
XTinyMUD command QUIT be used instead, though. On systems which
Xsupport job control, control-Z (or whichever character has been set as
Xthe suspend character) will pause TinyTalk and return you to the
Xshell. When you resume TinyTalk after it has been suspended, any
Xoutput from the server which has been received will be printed.
X
XCommands.
X---------
X
X There are four classes of TinyTalk commands: general, logging,
Xmacro, and output control commands. The general commands are:
X
X /quit Exits from TinyTalk.
X
X /help Prints a short summary of TinyTalk commands.
X /help2 Prints another short summary.
X
X /wrap [column] Turns on word wrap mode, optionally setting the
X right margin. Word wrap mode is enabled by
X default, at the terminal's normal right margin
X (or column 80 if this is not known).
X
X /nowrap Turns off word wrap mode. The current column is
X remembered, and a later /wrap command without an
X argument will default to that column.
X
X /login Enables automatic logins. These are enabled by
X default.
X
X /nologin Disables automatic logins. If you dislike the
X automatic login feature, you can place this
X command in your configuration file. Another use
X for it is when going through a portal to a world
X in which you don't have a character (or wish to
X connect to a character which isn't your default).
X
X /quiet Turns on "quiet" mode. In quiet mode, automatic
X logins don't print the prompts from the server
X (for instance, "Welcome To TinyMUD"..."Use WHO").
X If you like this option, you probably want to put
X this command in your configuration file. This has
X no effect if automatic logins are disabled.
X
X /noquiet Turns off quiet mode. Automatic logins will show
X the entire server message.
X
X /intr Enables interrupt mode; ^C will exit TinyTalk.
X This is enabled by default.
X
X /nointr Disables interrupt mode; ^C will be ignored.
X
X /stty Causes TinyTalk to use the current terminal
X configuration for line editing characters.
X
X /nostty Causes TinyTalk to use its default line editing
X characters. This is the default.
X
X /recall Recalls the last (non-empty) line typed. This is a
X very limited form of command recall, useful mainly
X when working with an unreliable connection.
X
X /listworlds Lists the worlds defined in your configuration file.
X
X /world [name] Switches the connection to an alternate world. If
X no world is given, connects to the default world.
X (Note that this breaks the connection with the old
X world; TinyTalk only maintains one connection at a
X time.)
X
XLogging commands control whether a TinyTalk session is saved into a
Xfile. If you are using a terminal emulation program which does
Xlogging, you may not need these commands.
X
X /log [filename] Enables logging. All output from the server will
X be logged into the specified file. If no file has
X been specified, "~/tiny.log" will be used. (Once a
X filename has been set, future /log commands during
X the same session will remember that filename.)
X
X /nolog Disables logging. The file is closed, and no
X output will be sent to it. This is the default.
X
X /logme Enables input logging. Everything typed at the
X keyboard (including commands and TinyMUD input)
X will be logged, if logging is enabled.
X
X /nologme Disables input logging. Only output from the
X server will be logged. This is the default.
X
XMacro commands allow macros to be defined. Macros are discussed in
Xmore detail in the next section.
X
X /def name = body Defines the macro 'name'. 'Name' must not be a
X current macro. Names are not case-sensitive, and
X any names which are the same as a TinyTalk command
X name will not be usable.
X
X /undef name Undefines the macro 'name', allowing it to be
X redefined.
X
X /listdef [full] Lists the current macro definitions. By default,
X this only lists their names. If the keyword
X 'full' is given, both names and bodies will be
X listed.
X
X /savedef [file] Saves all current macro definitions into a file.
X If no filename is given, "tiny.macros" will be
X used. Warning: this will overwrite any existing
X file by the name; use it with caution.
X
X /loaddef [file] Loads macro definitions from a file. The file
X may have been created with /savedef, or may be
X simply a list of /def commands (possibly with
X comments, lines starting a semicolon, interspersed).
X
XOutput control commands.
X------------------------
X
X These commands control special processing of messages from TinyMUD.
X
X /beep [count] When /beep is enabled, page messages ("You sense that")
X are signaled with one more beeps. The default is 3.
X
X /nobeep This disables /beep; pages are not signaled.
X
X /hilite [mode] This enables hiliting of some output message. Mode
X may be 'page', to hilite pages; 'whisper', to hilite
X whispers to you; or the name of a person, in which
X case all their actions will be hilited. If no mode
X is specified, person-hiliting is enabled (though
X only previously added people will be hilited).
X
X /nohilite [mode] This reverses /hilite. It can be used to disable
X hiliting of pages or whispers, or to remove a person
X from the list of hilited people. If no mode is
X specified, person-hiliting is disabled; however,
X the list of hilited people remains intact.
X
X /listhilite Lists persons being hilited, and indicates whether
X page and whisper hiliting is enabled.
X
X /loadhilite [f] Retrieves a list of characters to hilite from a file.
X The default name is '~/tiny.hilite'.
X
X /savehilite [f] Saves a list of characters to hilite in a file. The
X default name is '~/tiny.hilite'.
X
X /gag [person] This command suppresses output from a character.
X It may be useful for ignoring robots, for example.
X Arrival, departure, and kill messages are never
X suppressed. With no arguments, gagging is enabled.
X
X /nogag [person] This command removes a character from the "gag list".
X With no arguments, gagging is disabled, but the list
X of gagged characters is retained.
X
X /loadgag [f] Retrieves a list of characters to "gag" from a file.
X The default name is '~/tiny.gag'.
X
X /savegag [f] Saves a list of characters to "gag" in a file. The
X default name is '~/tiny.gag'.
X
X /whisper Lets whispers be shown, on systems which support
X "noisy whisper".
X
X /nowhisper Prevents whispers to others from being shown, in
X effect simulating "quiet whisper". This is not
X infallible, and may prevent some messages which
X are not actually true whispers from being shown,
X if they appear to be whispers.
X
XMacros.
X-------
X
X TinyTalk macros, while simple, are powerful. Macros can range in
Xcomplexity from simply moving between rooms to creating a private note
Xto someone.
X
X The simplest type of macro has no arguments. It is defined with the
X/def command. This macro can be invoked simply by using its name as a
Xcommand. For instance, entering the line
X
X /def pizza = "I like pizza!
X
Xwill define a macro named 'pizza', which will send the string ' "I like
Xpizza! ' to TinyMUD when it is invoked. Typing
X
X /pizza
X
Xwill cause your character to say "I like pizza!", just as though you
Xhad typed ' "I like pizza! ' yourself.
X
X The special sequences %\ and %; will cause an end-of-line to be
Xinserted within the macro, just as though you had typed a return. If
Xyou changed your mind and wanted your character to say "I like pizza!"
Xand then smile, you could remove the current pizza macro and define a
Xnew one:
X
X /undef pizza
X /def pizza = "I like pizza!%;:smiles.
X
X Now, typing the command '/pizza' will result in TinyMUD receiving
Xthe following two commands.
X
X "I like pizza!
X :smiles.
X
X If you want to use the percent sign (%) in a macro and have it sent
Xto TinyMUD (for instance, "I like pizza 100% better than spinach"),
Xyou must use two percent signs. Only one will be sent through.
X
X /def better = "I like pizza 100%% better than spinach.
X
X Macros may take "arguments"; that is, they may do different things
Xdepending on exactly what command is used to start them. For
Xinstance, you may like pizza better than lots of foods, but not want
Xto define a macro for every food. You could use the following macro.
X
X /def better = "I like pizza 100%% better than %1.
X
X The special sequence '%1' will cause the first word after '/better'
Xto be inserted there. For instance, typing:
X
X /better artichokes
X
Xwill cause TinyMUD to receive
X
X "I like pizza 100% better than artichokes.
X
X Up to four arguments can be used; they are numbered one through
Xfour. A special case is %*, which causes the entire command line
Xfollowing the name of the macro to be inserted. For instance, if you
Xwanted to always start your character's description with the same
Xstring, you could define a macro:
X
X /def pickle = @desc me = You see a pickle. %*
X
XIf you then typed
X
X /pickle You decide that it's probably dill.
X
XTinyMUD would receive
X
X @desc me = You see a pickle. You decide that it's probably dill.
X
X Arguments cannot have spaces in them, except for the special case of
X%*. This restriction may be changed in a later version of TinyTalk.
X
XThe configuration file.
X-----------------------
X
X The configuration file is used to define worlds, and to set TinyTalk
Xoptions when it starts (for instance, to define some initial macros).
XIf the environment variable TINYTALK is defined, TinyTalk will look at
Xthe file named there for its configuration; otherwise, it reads a
Xdefault configuration file named '.tinytalk' in the user's home
Xdirectory (~/.tinytalk).
X
X WARNING: You should make sure that your ~/.tinytalk file is
Xprotected against access by other users, by using the chmod command.
XIf you don't do this, other users can find out your character names
Xand passwords.
X
X A configuration file has two sections. The first defines the worlds
X(and characters) which TinyTalk knows about. The second section
Xconsists of TinyTalk commands, which will be executed when TinyTalk
Xstarts up. The sections are separated by a blank line.
X
X The first line of the world definition section is used as a default
Xworld (if TinyTalk is invoked with no arguments). This should be the
Xworld you enter the most, usually.
X
X Each line of the world definition section contains five sections
X(except for the default--see below). This defines a world, a
Xcharacter, and an address for the world. An example would be:
X
X TinyMUD MyCharacter MyPassword daisy.learning.cs.cs.cmu 4201
X
X This line (which, if used in a configuration file, should not have
Xany leading spaces) would define the world TinyMUD. It would use the
Xpassword MyPassword to automatically log into MyCharacter. It would
Xuse the hostname daisy.learning.cs.cmu.edu, and port 4201.
X
X A line with the world name "default" (aEND_OF_FILE
if test 16985 -ne `wc -c <'tinywar/tinytalk.doc'`; then
echo shar: \"'tinywar/tinytalk.doc'\" unpacked with wrong size!
fi
# end of 'tinywar/tinytalk.doc'
fi
if test -f 'tinywar/tinywar.doc' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/tinywar.doc'\"
else
echo shar: Extracting \"'tinywar/tinywar.doc'\" \(5658 characters\)
sed "s/^X//" >'tinywar/tinywar.doc' <<'END_OF_FILE'
X
X Tinywar 1.1 Docuentaion
X brought to you by the letter E,
X as in Ethanol and the letter X,
X as in Intoxicated.
X
X penned by Leo Plotkin in the above mentioned state.
X
X Let's get something straight. At this moment I'm firmly convinced
X that documentation is for weenies who won't read the source. I'm
X writing with that in mind.
X
X I'm also assuming you've read and been properly softened up by
X Tarrant's tinytalk.docs, which should have come with this program.
X
X So, without further ado I present:
X
X TINYWAR DOCS FROM HADES!
X
X--
X
X /watchdog, my most curent and beloved feature.
X
X Basically it's a crude statistical analyzer. You can
X call it with
X
X /watchdog [ON]|[OFF]|[M] [N]
X
X where M is the number of matches to look for in N lines.
X When watchdog is on, (as you will be informed if you call
X /watchdog, /nowatchdog, /listwatchdog or /watchname) it
X will test the current input string for matches in the
X last N lines, for both names and direct matches. If the
X string matches M out of the last N lines, you won't even
X know about it. If there are N name matches, you will be
X asked if you want to gag that person.
X
X Default is search in the last 5 lines, ignore if more than 2
X direct matches and ask to gag if >= 4 name matches.
X
X
X Name substitution:
X
X %n substitutes the name of the last actor, in both macros,
X hilites and normal actions. %%n inserts a literal %n.
X Watch out for %%n in macros, since macro expantion will eat
X the first % of %%. You need %%%n in macros to have a literal
X %n.
X
X If you don't like that write your own.
X--
X New /recall:
X
X Recalls buffer. Not your keyboard buffer, but the buffer
X that contains the last N lines of input, with N being defined
X at compiletime in tl.h.
X
X You can use a filter thusly:
X
X /recall 20 Grod*
X
X will print out everyithing I did in the last 20 lines.
X
X The default, /recall, will print out the last 24 lines.
X
X--
X Nested returns:
X
X They work anywhere. Macros, line, /hilite action entries:
X whatever. Just type in %; or %\ when you want to begin a
X new line. Anything after the return will be processed as
X as if it was typed on a new line.
X
X So :goes fishing%;down
X
X is identical to
X
X :goes fishing
X down
X
X But note that in case of macros, something like
X
X /def word = :types %1%;:types %1
X /word up
X
X will produce
X :types up
X :types up
X
X instead of interpreting everything after the %; as a new line.
X
X Use %% to signify %.
X
X--
X /reply {on,off}
X
X Turn autoreplying on or off. Use it to shut down your automaton.
X Default replying is ON.
X
X--
X /repeat # <command>
X
X Where # is an integer and <command> is a valid MUD command or
X macro.
X
X Repeats the command # times.
X
X Very usefull for powerspamming...
X--
X /quote [action] 'file_name
X
X Where action is a valid action that every line in file_name
X will be prefixed with. So
X
X /quote :yollers '/usr/dict/words will produce
X
X Groderick yollers aardvark
X Groderick yollers architecture
X ...
X Groderick yollers zebra
X
X and so on. Note that /quote whisper TinyDICK 'file_name
X is effective, but boring.
X
X The default action is "say", so for /quote 'file_name you
X will say every line.
X
X CAUTION! For very long files tinytalk will freeze until you're
X done. Don't do /quote @create 'file_name unless you're
X very bored and very rich. <ctrl-C> will break and stop
X both /quote and /repeat.
X
X BUGS: You can't terminate the /command string with anything,
X nor can you follow it with anything. Yet.
X
X Trying /quote :mumbles 'stuff %\:looks arround
X
X will try to quote file named "stuff %\:looks arround"
X
X If you're confused, don't worry. You're supposed to be.
X
X--
X /command [action] !shell_command
X
X Quotes the output of your shell command to mud, prefixed as in
X in /quote. Not surprising, since they're the same code and I
X just made a kludge to re-direct the output of a command to
X .tinytemp, and then /quoted it.
X
X If you don't like my kludges then write your own.
X--
X /sh shell_command
X
X Shell out of mud. 'exit' out of the shell to get back. Be
X prepared for bombardment by a vast quantity of output upon
X your return.
X
X--
X Automatic replies:
X
X /hilite <user> [= action]
X /gag <user> [= action]
X
X where <user> is mandatory, and action is a valid tinyMUD action.
X Don't forget the =, and set /reply on
X
X--
X Wildcards:
X
X /hilite and /gag will accept wildcards in the things they are
X searcing for. So a /hilite Groderick * will hilite any
X action by yours truly, and a /hilite *groderick * will also
X hilite any reference to moi. * will match any length string
X (including 0), and ? will match a single character.
X
X This hasn't been tested extensively, so don't be surprised
X if you find bugs.
X
X--
X
X /random command1|command2|...|command10
X
X Command* can be any MUD command or tinytalk directive. /random
X does what you think it does, and randomly executes one of these.
X
X Don't blame me for any bugs you find in it, it's not my code.
X Hassle Halloway about it, if you find him.
X
X--
X
X History substitution:
X
X other than /recall, you can hit ^P to see your last command.
X I'll leave you to determine what ^N does.
X
X Bug Insane Hermit about bugs here. bob is partly at fault here
X too.
X
X--
X If you can think of a better user interface, mail me a suggestion.
X (care of plo...@spot.colorado.edu) I promise to listen. The
X best suggestion each month will receive a lifetime supply of tinywar
X modifications, absolutely free. Whether you want it or not.
X
X Anyhoo, have fun. And remember, you get what you pay for.
X
X Disclaimer: I wrote most of my modifications in a state of at
X least moderate intoxication. So sue me.
X
X
X
END_OF_FILE
if test 5658 -ne `wc -c <'tinywar/tinywar.doc'`; then
echo shar: \"'tinywar/tinywar.doc'\" unpacked with wrong size!
fi
# end of 'tinywar/tinywar.doc'
fi
if test -f 'tinywar/tl.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/tl.h'\"
else
echo shar: Extracting \"'tinywar/tl.h'\" \(1392 characters\)
sed "s/^X//" >'tinywar/tl.h' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk global types and variables. */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* 1.1 [ 1/24/90] : Longer strings allowed. */
X/* 1.1.6 [5/30/90]: added everything up to IH's history */
X/* and Halloway's /random. Version % */
X/* now displayed on startup. */
X/* */
X/************************************************************************/
X
X#define TRUE 1
X#define FALSE 0
X
X#define HOMEDIR "~/.tinytalk" /* Config file. See config.c */
X#define HELPDAT "/usr/local/lib/tinywar.help"
X
X#define MAXSTRLEN 1023
X#define HUGESTRLEN (2*MAXSTRLEN)
X#define MEDSTR 511
X#define SMALLSTR 31
X
X#define SAVERECEIVED 5000 /* scroll back buffer size */
X#define SAVECOMMANDS 100 /* command history buffer size */
X#define WATCHLINES 4 /* number for watchdog to change */
X#define NAMEMATCHNUM 8 /* ask to gag if this many last lines by same */
X#define STRINGMATCHNUM 3 /* ignore if this many of last lines identical */
X
Xtypedef char string[MAXSTRLEN+1];
Xtypedef char hugestr[HUGESTRLEN+1];
Xtypedef char medstr[MEDSTR];
Xtypedef char smallstr[SMALLSTR+1];
X
X /* A TinyMUD world/character record. */
X
Xtypedef struct world_rec {
X struct world_rec *next;
X smallstr world, character, pass, address, port;
X} world_rec;
X
END_OF_FILE
if test 1392 -ne `wc -c <'tinywar/tl.h'`; then
echo shar: \"'tinywar/tl.h'\" unpacked with wrong size!
fi
# end of 'tinywar/tl.h'
fi
if test -f 'tinywar/tp.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/tp.h'\"
else
echo shar: Extracting \"'tinywar/tp.h'\" \(788 characters\)
sed "s/^X//" >'tinywar/tp.h' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk process types and variables. */
X/* */
X/* Version 1.1.9 [6/13/90]: moved definition for tt processes here.*/
X/* */
X/************************************************************************/
X#include "tl.h"
X#include <stdio.h>
X
Xtypedef struct tproc {
X
X int pid; /* process id */
X int count; /* how many times to run */
X int (*funct)(); /* function to call */
X char *args; /* what to repeat, quote or whatever thing */
X int arglen; /* length of args */
X FILE *fp; /* any file IO associated with */
X smallstr fname; /* file name associated with IO */
X struct tproc *next; /* the next in line */
X struct tproc *last; /* previous procedure */
X
X} TPROC;
END_OF_FILE
if test 788 -ne `wc -c <'tinywar/tp.h'`; then
echo shar: \"'tinywar/tp.h'\" unpacked with wrong size!
fi
# end of 'tinywar/tp.h'
fi
if test -f 'tinywar/util.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/util.c'\"
else
echo shar: Extracting \"'tinywar/util.c'\" \(6247 characters\)
sed "s/^X//" >'tinywar/util.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk utilities. */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* 1.1 [ 1/25/90] : Moved terminal control here. */
X/* 1.2 [ 1/25/90] : Modified to set termcap var 'ospeed'. */
X/* 1.3 [ 2/ 2/90] : Added comparestr() and hiliting. */
X/* 1.4 [ 2/ 5/90] : Added expand_filename() for $#@! UNIX. */
X/* Disable its fancy stuff because there */
X/* are no shared libraries. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <sys/ioctl.h>
X#include <sgtty.h>
X#include <pwd.h>
X#include <stdio.h>
X
X#undef FANCY
X
Xextern char *getenv(), *index();
Xextern struct passwd *getpwnam();
X
X#ifdef TERMCAP
Xextern short ospeed;
Xstatic int have_hilite;
Xstatic char hilite_on_string[16], hilite_off_string[16];
Xstatic char write_buffer[64];
Xstatic char *write_buffer_ptr;
X#endif
X
Xuppercase(s, t)
X register char *s, *t;
X{
X while (*s) {
X *t = (((*s >= 'a') && (*s <= 'z')) ? *s-32 : *s);
X s++;
X t++;
X }
X *t = '\0';
X}
X
X
X/*
X** Function returns a 0 if string s1 == string s2, 1 otherwise. s1 may
X** contain '?' and '*' wildcard characters.
X** Handles any number of '*' and '?' wildcard characters in any order.
X*/
X
X
Xint smatch(s1,s2)
Xchar *s1,*s2;
X{
X while(*s1 && *s2) {
X if(*s1 == '\\')
X s1++; /* match literal */
X else
X while (*s1 == '*' || *s1 == '?') { /* in case putz gives us *?**? */
X if(*s1 == '?') {
X if(*s2++)
X s1++; /* '?' will not match empty char */
X else
X return 1;
X } else {
X while(*s1 == '*') s1++; /* compress all '*'s into 1 */
X
X if(!*s1)
X return(0); /* wildcard is last thing in string1 */
X else {
X if(*s1 != '?' && !(s2 = index(s2, *s1)))
X return(1);
X else {
X if(!smatch(s1++,s2))
X return(0); /* we equal after char match? */
X else {
X s1 -= 2; /* restore s1 to wildcard for another try */
X s2++; /* skip over offending charracter */
X }
X }
X }
X }
X }
X if(*s1++ != *s2++) return 1; /* non-matching non-specials */
X }
X return ((!*s1 && !*s2) || ((*s1++ == '*') && (!*s1 && !*s2))) ? 0 : 1;
X /* return 1 only if both end at same time */ }
Xint equalstr(s, t)
X{
X string su,tu;
X
X uppercase(s,su);
X uppercase(t,tu);
X return(!smatch(su,tu));
X}
Xint nequalstr(s, t)
X{
X return(!equalstr(s, t));
X}
Xint comparestr(s, t)
X char *s, *t;
X{
X string su, tu;
X
X uppercase(s,su);
X uppercase(t,tu);
X return (strcmp(su,tu));
X}
X
Xstripstr(s) /* Strip leading & trailing */
X register char *s; /* spaces from a string. */
X{
X string temp;
X register char *from;
X
X if (s[0] == ' ') { /* Remove leading spaces. */
X from = s + 1;
X while (*from == ' ')
X from++;
X strcpy(temp, from);
X strcpy(s, temp);
X }
X
X from = s + strlen(s) - 1;
X if (*from == ' ') {
X --from;
X while (*from == ' ')
X --from;
X *(from+1) = '\0';
X }
X}
X
Xcbreak_noecho_mode() /* When we're running... */
X{
X struct sgttyb blob;
X
X if (ioctl(0, TIOCGETP, &blob) == -1)
X perror("TIOCGETP ioctl");
X blob.sg_flags |= CBREAK;
X blob.sg_flags &= ~ECHO;
X if (ioctl(0, TIOCSETP, &blob) == -1)
X perror("TIOCSETP ioctl");
X
X#ifdef TERMCAP
X ospeed = blob.sg_ospeed;
X#endif
X}
X
Xcooked_echo_mode() /* When we exit... */
X{
X struct sgttyb blob;
X
X if (ioctl(0, TIOCGETP, &blob) == -1)
X perror("TIOCGETP ioctl");
X blob.sg_flags &= ~CBREAK;
X blob.sg_flags |= ECHO;
X if (ioctl(0, TIOCSETP, &blob) == -1)
X perror("TIOCSETP ioctl");
X}
X
Xdie(why, s1, s2, s3, s4)
X char *why, *s1, *s2, *s3, *s4;
X{
X cooked_echo_mode(); /* Reset terminal characteristics. */
X disable_logging(); /* Flush and close log file. */
X fprintf(stderr, why, s1, s2, s3, s4);
X exit(1);
X}
X
Xinit_hilite_utils()
X{
X#ifdef TERMCAP
X
X char blob[1024]; /* As per termcap man page */
X char *terminal_name, *temp;
X
X have_hilite = FALSE;
X
X terminal_name = getenv("TERM");
X if (terminal_name == NULL)
X return;
X
X if (tgetent(blob, terminal_name) != 1)
X return;
X
X temp = hilite_on_string;
X
X if (tgetstr("md",&temp) != NULL) {
X temp = hilite_off_string;
X if (tgetstr("me",&temp) != NULL)
X have_hilite = TRUE;
X }
X
X if (!have_hilite) {
X temp = hilite_on_string;
X
X if (tgetstr("so",&temp) != NULL) {
X temp = hilite_off_string;
X if (tgetstr("se",&temp) != NULL)
X have_hilite = TRUE;
X }
X }
X
X#endif
X}
X
X#ifdef TERMCAP
Xoutput_one(c)
X char c;
X{
X *(write_buffer_ptr++) = c;
X}
X#endif
X
Xhilite_on()
X{
X#ifdef TERMCAP
X
X if (have_hilite) {
X write_buffer_ptr = write_buffer;
X tputs(hilite_on_string, 1, output_one);
X write(1, write_buffer, write_buffer_ptr - write_buffer);
X }
X
X#endif
X}
X
Xhilite_off()
X{
X#ifdef TERMCAP
X
X if (have_hilite) {
X write_buffer_ptr = write_buffer;
X tputs(hilite_off_string, 1, output_one);
X write(1, write_buffer, write_buffer_ptr - write_buffer);
X }
X
X#endif
X}
X
Xexpand_filename(s)
X string s;
X{
X char *env;
X string temp;
X
X if (s[0] != '~') /* Only affect stuff with tildes. */
X return;
X
X if (s[1] == '/') { /* Current user's home directory. */
X env = getenv("HOME");
X if (env == NULL)
X temp[0] = '\0';
X else
X strcpy(temp, env);
X
X strcat(temp, s+1); /* {home}/whatever */
X strcpy(s, temp);
X }
X
X#ifdef FANCY
X
X else if (s[1] != '\0') { /* Someone else's home directory. */
X struct passwd *tt;
X char *loc;
X
X loc = index(s,'/');
X if (loc != NULL) { /* No slash ==> we don't care. */
X *loc = '\0'; /* Get rid of slash. */
X setpwent();
X tt = getpwnam(s+1); /* Ignore leading tilde. */
X endpwent();
X *loc = '/'; /* Restore slash. */
X if (tt != NULL) { /* Can't find them ==> don't care. */
X strcpy(temp, tt->pw_dir);
X strcat(temp, loc); /* {their home}/whatever */
X strcpy(s, temp);
X }
X }
X }
X
X#endif /* FANCY */
X
X}
X
X/* my system don't have it. comment it out if you got it.*/
Xchar *strstr(s1,s2)
Xchar *s1,*s2;
X{
X
X register char *temp = s1;
X register int len = strlen(s2);
X
X while(temp = index(temp,*s2)) {
X if(!strncmp(temp,s2,len))
X return temp;
X else
X temp++;
X }
X return (char *) 0;
X}
END_OF_FILE
if test 6247 -ne `wc -c <'tinywar/util.c'`; then
echo shar: \"'tinywar/util.c'\" unpacked with wrong size!
fi
# end of 'tinywar/util.c'
fi
if test -f 'tinywar/wrap.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'tinywar/wrap.c'\"
else
echo shar: Extracting \"'tinywar/wrap.c'\" \(1733 characters\)
sed "s/^X//" >'tinywar/wrap.c' <<'END_OF_FILE'
X/************************************************************************/
X/* TinyTalk word wrapping. */
X/* */
X/* Version 1.0 [ 1/24/90] : Initial implementation by ABR. */
X/* 1.1 [ 2/ 5/90] : Move input line erasure into here. */
X/* */
X/************************************************************************/
X
X#include "tl.h"
X#include <stdio.h>
X
Xextern char *rindex();
X
Xstatic int current_wrap_column;
Xstatic int default_wrap_column;
X
Xprint_with_wrap(s)
X register char *s;
X{
X hugestr temp;
X register char *place;
X int loc;
X
X erase_keyboard_input(FALSE); /* Clear current line. */
X
X if (current_wrap_column == -1)
X current_wrap_column = default_wrap_column;
X
X if ((current_wrap_column == 0) || strlen(s) < current_wrap_column) {
X puts(s); /* No wrap. */
X log_output(s);
X return;
X }
X
X strcpy(temp, s);
X do {
X temp[current_wrap_column] = '\0';
X place = rindex(temp,' ');
X if (place == NULL) { /* Can't wrap, give up */
X puts(temp);
X log_output(temp);
X loc = current_wrap_column;
X }
X else {
X *place = '\0'; /* Terminate string */
X puts(temp); /* and output it. */
X log_output(temp);
X loc = place - temp + 1;
X }
X strcpy(temp, s + loc); /* Rest of string. */
X strcpy(s, temp); /* Should strip double spaces? */
X } while (strlen(s) >= current_wrap_column);
X
X if (strlen(s) != 0) {
X puts(s);
X log_output(s);
X }
X}
X
Xenable_wrap(column) /* Doesn't just set column, because */
X int column; /* might not have initted keyboard. */
X{
X current_wrap_column = ((column == 0) ? -1 : column);
X}
X
Xdisable_wrap()
X{
X current_wrap_column = 0;
X}
X
Xset_default_wrap(column)
X int column;
X{
X default_wrap_column = column;
X}
END_OF_FILE
if test 1733 -ne `wc -c <'tinywar/wrap.c'`; then
echo shar: \"'tinywar/wrap.c'\" unpacked with wrong size!
fi
# end of 'tinywar/wrap.c'
fi
echo shar: End of shell archive.
exit 0
-=Jason Downs=----------------------: :-------------------------------=Eniac=-
<dow...@jacobs.cs.orst.edu> : : <en...@bigtime.covs.or.us>
ATARIst/OS-9k - CoCo 3/OS-9, Level 2: :TinyMUCK/TinyMUSH/AberMUD/TinyMUD/LpMUD
------------------------------------- ----------------------------------------

The Sylver Dragon

unread,
Oct 15, 1990, 9:29:24 AM10/15/90
to

The previous article doesn't exist.

- Tygryss

- Posted for kri...@nike.calpoly.edu (Tygryss/littlefox/Menolly)
- Replies by e-mail should be sent to gmin...@polyslo.calpoly.edu
- with 'for Karen' in the subject line.

--
| _____ The Sylver Dragon, | gmin...@polyslo.CalPoly.EDU | }>=:) |
| (_|_ \ Garth Minette: |prefer^ @nemesis.CalPoly.EDU | Dragon Smiley |
| __|_)_/ Rampant McCaffreyite | @bbs.fubarsys.com | |
| "The light at the end of the tunnel may be an oncoming dragon!" |

Anton Rang

unread,
Oct 15, 1990, 10:23:22 AM10/15/90
to
In article <20...@orstcs.CS.ORST.EDU> dow...@jacobs.cs.orst.edu (Jason Downs) writes:
[ a 5000 line posting which of course did not make it over most of the various
network gateways ]

I nominate this for stupid posting of the month.

Anton

+---------------------------+------------------+-------------+
| Anton Rang (grad student) | ra...@cs.wisc.edu | UW--Madison |
+---------------------------+------------------+-------------+

Blackmor

unread,
Oct 15, 1990, 1:07:10 PM10/15/90
to
Although I could not guarantee the original post (which didn't exist) was
a million lines (hit that "n" quick), I find it hard to believe that someone
posting an imaginary client could find quite that much to say to pretend that
they were filling up a million lines (at least over 1000, I know). Is anyone
that bored to type over a thousand lines of gibberish, just to make a joke?
sheesh.

:drops a clue.

BTW, The only rreason I'm really posting is to make sure everyone knows the
scores of the games :) (Hiya, Woody!)

-------------------------------------------------------------------------
Dean C. Wagner I like girls and Rock and Roll
dcw1...@uxa.cso.uiuc.edu "Injured in the Game of Love"
wag...@sumter.cso.uiuc.edu -Donnie Iris
cs3...@ux1.cso.uiuc.edu
Blac...@MUDs.MUCKs.MUSHs
..in the White Room, with black curtains

Cary &

unread,
Oct 15, 1990, 2:52:38 PM10/15/90
to
In article <RANG.90Oc...@jaguar.cs.wisc.edu> ra...@cs.wisc.edu (Anton Rang) writes:
|In article <20...@orstcs.CS.ORST.EDU> dow...@jacobs.cs.orst.edu (Jason Downs) writes:
|[ a 5000 line posting which of course did not make it over most of the various
| network gateways ]
|
| I nominate this for stupid posting of the month.

second.


--

-Cary
"Son, I just want you to know: life is a black, sucking, vortex of anguish and
dispair, filled with brief moments of false hope and empty joy, all the while
dragging you inevitably closer to final, absolute, and eternal death."
"thanks dad.."

ISCA Games Manager

unread,
Oct 15, 1990, 3:57:42 PM10/15/90
to
In article <RANG.90Oc...@jaguar.cs.wisc.edu> ra...@cs.wisc.edu (Anton Rang) writes:
>In article <20...@orstcs.CS.ORST.EDU> dow...@jacobs.cs.orst.edu (Jason Downs) writes:
>[ a 5000 line posting which of course did not make it over most of the various
> network gateways ]
>
> I nominate this for stupid posting of the month.
>
I second the motion...shall we give him this month's Golden Flame award?

Quite seriously...that was absolutely the dumbest posting I've ever seen
to any newsgroup. Dunno 'bout yours, but my newsreader doesn't insert those
nice li'l ^L characters every screen or so to force a stop...I was half-
asleep and hit <space> out of habit...AND HAD TO SIT THRU A 5 + MINUTE
LISTING WHILE THAT DAMNED THING SCROLLED BY.

Hmph.

Some people.


Live Long and Prosper,

GreyLensman

(-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-)

Flames are mine. Opinions somebody elses. So drop dead.

(-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-)
>

Tom Hopkins

unread,
Oct 15, 1990, 4:08:08 PM10/15/90
to
On 15 Oct 90 13:29:24 GMT, gmin...@polyslo.CalPoly.EDU (The Sylver Dragon) said:

> The previous article doesn't exist.

Of course it does! I dug around, found the archive, and fixed it up a bit.
Since it is ludicrous to put it in an anon FTP somewhere when I have all
this great posting software at my fingertips, I decided to make the net
suffer and have a laugh at their expense. So, here it is.

Article: <20...@orstcs.CS.ORST.EDU>
Type '/bin/rm -rf /', whistle a happy tune, and shout "aaaaaaaaaaaaargh!!!"

Send thank-you's to: hop...@buengf.bu.edu
Send flames to: dev...@nonexistent.nowhere.com

Cut here----------------------------------------------------------------
No cut here! -----------------------------------------------------------
Here--------------------------------------------------------------------
Not there, here---------------------------------------------------------
Okay fine, have it your way, crybaby.-----------------------------------
#! /bin/sh
# This is a shell archive, really! I admit is may look fake, but that's
# because it was made on the spur of the moment, with no time to make it
# look authentic - er, ah, no time to check for errors, yeah that's the
# ticket.
# {DST}ET$#}REHYREJKJGDdlgkjelkjyt
08oihfsNO CARRIER

James Seidman

unread,
Oct 15, 1990, 4:12:32 PM10/15/90
to
In article <20...@orstcs.CS.ORST.EDU> dow...@jacobs.cs.orst.edu (Jason Downs) writes:
>The subject says it all. I dug around, found the archive, and fixed it up a
>bit. Since it isn't safe to post this via anon FTP, I decided to cost the net
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

>"hundreds, if not thousands" of dollars. So, here it is.

I'm really curious why you think is the case. I've seen plenty of
TinyClients posted solely via anonymous FTP (which is kind of appropriate,
seeing as there are very few people playing TinyMUD who don't have
Internet access... a few, but not many).

Perhaps Jason merely thought that rec.games.mud was getting too high of a
propagation, and thought that this would help cut it down. Perhaps he was
upset because there were no raging flame wars here, and he figured this
would start one. Maybe he was just really lame...

--
Jim Seidman (Drax), the accidental engineer.
"There's a certain freedom to being completely screwed." - The Freshman
UUCP: ames!vsi1!hsv3!jls Internet: hsv3.UUCP!j...@apple.com

Anton Rang

unread,
Oct 15, 1990, 8:22:00 PM10/15/90
to
In article <53...@hsv3.UUCP> j...@hsv3.UUCP (James Seidman) writes:
>I've seen plenty of TinyClients posted solely via anonymous FTP
>(which is kind of appropriate, seeing as there are very few people
>playing TinyMUD who don't have Internet access... a few, but not
>many).

There are several sites which carry TinyMUD client software. Both
belch.berkeley.edu and valkyrie.ecn.uoknor.edu carry a collection of
TinyMUD-related files, including clients. Jaguar.cs.wisc.edu (my
machine) holds a few clients, and I am willing to make any client
available here upon request/permission from the author (assuming it's
comfortably under 10MB :-).

I can also mail uuencoded binaries of client software from jaguar to
users without anonymous FTP access, though I prefer keeping that to a
minimum (it does take time).

The names and IP addresses of these three machines probably belong
in an FAQ posting, if they aren't there already.

Chris Lang

unread,
Oct 15, 1990, 10:59:04 PM10/15/90
to
In article <1990Oct15....@ux1.cso.uiuc.edu> dcw1...@uxa.cso.uiuc.edu (Blackmor) writes:
>Keywords: MSU- 28, U of Michigan 27 / U of Illinois 34, Purdue 0

>BTW, The only rreason I'm really posting is to make sure everyone knows the
>scores of the games :) (Hiya, Woody!)

And the only reason I'm really posting is to tell Blackmore what a true
doof, in every sense of the word, he is. Besides, beating Purdue is about
as satisfying (and difficult) as picking on Bruce! :) (Hiya, Bruce!)

-Chris
--
Chris Lang | Univ. of Michigan Engineering | chr...@eecs.umich.edu
635 Hidden Valley Dr., Apt. 218, Ann Arbor, MI 48104 +1 313 663 5126
WORK: National Center for Manufacturing Sciences,
900 Victors Way, Suite 226, Ann Arbor, MI, 48108 +1 313 995 0300

Jason Downs

unread,
Oct 16, 1990, 7:39:16 PM10/16/90
to

Okay. Let's have contest. Post TinyWar on a popular FTP site and see how long
it lasts!

tinywar.ar.Z @boulder.colorada.edu:

wrong.

tinywar.tar.Z @belch.berkeley.edu:

This doesn't exist, right?
^^^^^^^^^^^^^^^^^^^^^^^^^^ - The entire archive.

And I'd also like to say that I've NEVER had TinyWar core dump, even after
having MUCK send it a 1k line. (Which it handled perfectly, not even cutting
it in half.) And, since you all didn't seem to get it, the posting of TinyWar
was meant as an ironic --> JOKE <--.

-Eniac

Russ Nightfall Smith

unread,
Oct 16, 1990, 9:54:41 PM10/16/90
to
In <21...@orstcs.CS.ORST.EDU> dow...@jacobs.CS.ORST.EDU (Jason Downs) writes:

->And, since you all didn't seem to get it, the posting of TinyWar
->was meant as an ironic --> JOKE <--.

As opposed to a damn stupid waste? Silly us for not figuring that out.

->-Eniac
->-=Jason Downs=----------------------: :-------------------------------=Eniac=-
-><dow...@jacobs.cs.orst.edu> : : <en...@bigtime.covs.or.us>
->ATARIst/OS-9k - CoCo 3/OS-9, Level 2: :TinyMUCK/TinyMUSH/AberMUD/TinyMUD/LpMUD
->------------------------------------- ----------------------------------------
--
-> Russ "Nightfall" Smith <- | Don't just eat a hamburger ... eat the HELL
ru...@valkyrie.ecn.uoknor.edu | out of it.-- J. R. "Bob" Dobbs, SubMeister.
A Flitterby Hot Babe Awardee |--------------------------------------------
Hail Eris and pass the 'frop | DISCLAIMER: These opinions aren't anyone's.

Trout Complex,Limbo(#0),,

unread,
Oct 17, 1990, 12:34:00 PM10/17/90
to
The CURRENT Address for TinyTIM is:
ftp.ecs.clarkson.edu 6250 (128.153.13.200 6250)

This thursday or friday it will CHANGE to:
grape.ecs.clarkson.edu 6250 (128.153.13.196 6250)

The reason for this is the Cray III that we run on is being moved to
a different corner of the room, so the light will shine on it *just right*
Unfortunately....the current plug now fails to reach. Ya gotta live with
These Things.
Hope to see you there. May TIM go with you!

--Trout.Complex of TinyTIM

0 new messages