ICBM(1)

NAME
ICBM - An extensible threaded ICB client in Perl

VERSION
Version 1.7 ("Hot Date With A Perl Script")

SYNOPSIS
icbm [options]

  Options:
    -server <name>              (default: chime)
    -group <name>               (default: 1)
    -nick <name>                (default: username)
    -host <hostname>            (default: chime.icb.net)
    -port <port>                (default: 7326)
    -icbserverdb, db <path>
    -color, -turner
    -list
    -who
    -alacritty, -a
    -help, -usage, -?
    -man
    -version

OPTIONS

-server <name>
    Specify the server to use, by name (defaults to chime)

-group <name>
    Specify the initial group to join (defaults to group 1)

-nick <name>
    Specify the nickname to use in ICB (defaults to your username)

    -nick can be specified more than once.

-host <hostname>
    Specify the server to use, by hostname (defaults to chime.icb.net)

-port <number>
    Connect to the specified port (defaults to port 7236)

-icbserverdb, -db <path>
    Specify the fully qualified pathname of the icbserverdb file to use

-color, -turner
    Colorize messages in ICB

-list
    List the known ICB servers, do not connect

-who
    List users on the server, do not join server

-alacritty, -a
    Activate features for Alacritty compatibility to enable mousewheel scrolling in alacritty terminals. THIS DOES NOT WORK INSIDE SCREEN OR TMUX.

-help, -usage, -?
    List command-line options and usage, then exit

-man
    Display full documentation and exit

-version
    Display version string and exit

DESCRIPTION
ICBM is a threaded ICB client which supports a superset of the feature set of CICB, but scripted in Perl instead of TCL. The primary goal of ICBM is to be a lightweight ICB client that is not dependent upon TCL. TCL may well be traditional for ICB/ForumNet clients to embed, but come on, people, it's a ghastly language for most purposes.

ICBM's initial behavior is controlled by the command-line options listed above. Most options can be abbreviated to their first letter. All command-line options may be shortened to any unique form -- for instance, -n for -nick and -s for server. The presence of -turner as a synonym for -color is for historical reasons from the development of CICB's color code.

INITIALIZATION
On startup, ICBM will attempt to read the list of known ICB servers from the file icbserverdb, if it exists. ICBM will look for this file by default in the following paths:

    $HOME/.icbserverdb
    <data directory>/icbserverdb (see below)
    /usr/share/icb/icbserverdb
    /usr/local/share/icb/icbserverdb
    /usr/local/lib/icb/icbserverdb
    /usr/local/lib/icbserverdb
    /usr/lib/icb/icbserverdb
    /usr/lib/icbserverdb
    ./share/icb/icbserverdb

ICBM can also be instructed to look for the file in a specified location, either by including an icbserverdb directive in the defaults file, or by using the -db option. If a location is specified by either means, and an icbserverdb file is found there, the default list of locations will not be searched; if the specified location is not found, though, the search will continue.

This file is intentionally the same server list file used by CICB. ICBM will use the first of the listed files that it finds which is readable by the user and appears to be a text file.

The format of the icbserverdb file is as follows:

    server1     hostname        port
    server2     hostname        port
    server3     hostname        port
    ...

ICBM will use the contents of this file, if found, to resolve ICB server names to hostnames. If the icbserverdb file is not found, ICBM knows only about the current (as of the time of writing) default server, chime.icb.net, aka default.icb.net.

ICBM will next look for its startup files. By default, these are located in your $HOME/.icbm directory. This location can be overridden by setting the environment variable ICBM_DATA.

If the data directory does not exist the first time you run ICBM, ICBM will attempt to create it. ICBM will die with an error message if it cannot create the $HOME/.icbm directory (or $ICBM_DATA if ICBM_DATA is set), or if $HOME/.icbm (or $ICBM_DATA) already exists and is not a directory. (From here on, this directory will be referred to as $DATADIR.)

The very first data file ICBM will try to read is $DATADIR/defaults. This file should contain ONLY variable settings to be changed before ICBM sets up its windows, plus an optional list of default nicks. At present, this file supports setting the following defaults:

writesize <number of lines>
logbuffer <number of lines>
defserver <default server name>
defhost <default server hostname>
defport <default server port>
defgroup <default initial group>
encryption <0|1>
nick <nick> (may appear multiple times)
icbserverdb <path to icbserverdb>
debugmask <hexadecimal mask>
sleeptime <seconds>
timestamps <on|off|yes|no|1|0>
timestampformat <format>
dateinsignon <on|off|yes|no|1|0>

All of these are case insensitive, so you can say dateinsignon = on or DateInSignOn = True and it should work the same, regardless. For Boolean settings (timestamps and dateinsignon), any of yes, true, on, or 1 is accepted as 'on' and anything else is presumed to be 'off'.

The writesize is the number of lines ICBM sets aside for the writing pane in the terminal window. Its value defaults to 5, and may be set anywhere from 1 to 10. If a nick is specified in the defaults file, it will be used to seed the first value in the list of nicks (see below). If no server or host and port are specified on the command line, and no defaults are specified in the defaults file, then ICBM will fall back to the defaults 'chime', chime.icb.net, and port 7326. Likewise, if no group is specified in either place, the fallback group is group 1. The logbuffer default sets the number of incoming messages ICBM will cache in its FIFO buffer for replays; if not specified, it defaults to 500, and may be set to any integer value greater than 100.

Sleep time is the time ICBM will pause after initialization if debugging is enabled, or if warnings occur while initializing encryption modules. It defaults to 10 seconds.

The timestamp format can be any valid strftime format string. It is checked for general format validity, but not for sanity. It defaults to %H:%M:%S.

If dateinsignon is true, then ICBM will display the sign-on date in the Sign-On column. If
 is false, then ICBM will fall back to the classic cicb naive behavior of displaying only the sign-on time. The default is off.

If you started ICBM with the -color option, it will next look for $DATADIR/colors to find color definitions. If -color was used and no $DATADIR/colors file exists, ICBM will use its default colors. Be aware that these default colors are tuned for a terminal window or Xterm with a black background. (See COLORS, below.)

STARTUP MODES
What happens next depends on whether you started ICBM in non-interactive mode (icbm -who) or in interactive mode.

In a non-interactive (query-only) startup, ICBM will at this point simply attempt to connect to the ICB server, obtain a list of users on the server in visible groups, display the list on your screen, and exit.

In an interactive (log-in) startup, after doing initial color setup, ICBM divides your terminal window into three regions. The bottom five lines of the terminal are used for an input typing area (which scrolls as needed). The next line up is ICBM's status line, which displays various information about your connection (see THE STATUS LINE). The remainder of the terminal above the status line is used to display output from the server, which also scrolls as needed. The input window supports a readline-like history buffer with command-line editing (see EDITING), as well as a tab-history buffer of people whom you have messaged or who have messaged you (see TAB HISTORY).

After creating the terminal windows, ICBM will attempt to connect to the ICB server. If connection succeeds, ICBM will automatically load the default script file, $DATADIR/commands (assuming it exists). No other files will be autoloaded, but you can make ICBM load additional script files from your commands file if you wish (see SCRIPTING) or load them manually yourself as needed using the /load and /loadhook commands (see COMMANDS).

    IMPORTANT NOTE: Hook functions can be contained in the same file as regular scripting functions. However, at this time, it is necessary to use the loadhook command/function to load hook functions, as they must be loaded in the context of the loader thread, while regular scripting functions must be loaded using load. Therefore, if you mix hooks and regular functions in the same file, you must load that file twice using both load and loadhook. It is recommended that you keep your hooks and all other scripting functions in separate files.

    This limitation may be removed in a future release.

    You should also be aware that there is at this time no way for hooks and regular scripting functions to share any data not contained in existing ICBM shared variables, because they are executed in different threads.

After loading your command file(s), ICB will log you in to the server, and you're up and running, unless the nick you chose is already is use by another user on the server. In this case, the server will rather unceremoniously drop you, and you'll have to try again using a different nick.

ICBM allows you to specify more than one nick on the command line, as in the example below:

    icbm -n Larry -n Moe -n Curly

In this case, ICBM will first try to connect you to the server as Larry. If someone else is already logged on as Larry, ICBM will automatically try the connection again as Moe. If all supplied nicks fail, ICBM will make one more last-ditch attempt using what it has determined to be your login username, before giving up.

By default, you will join the server in group 1. Message traffic from the server appears in the top window (the read window), while you type your commands and messages in the bottom window. By default, your own outgoing messages are echoed to the read window, so that you can see what you said and when in the conversation you said it. (This feature can be disabled by setting the echo_outgoing variable to 0, as explained below in ICBM VARIABLES.)

ICBM maintains a log of up to the last 500 (by default) message packets received from the server, which can be "replayed" in the read window at any time using the /replay command (see ICBM COMMANDS). This does not include automatically-echoed outgoing messages.

ICBM allows you to edit the commands and messages you type in a similar manner to readline or emacs. It also has a capability for automatic correction of your own common typos using your own personal list of corrections (see the /correct command). This automatic correction can be disabled on a line-by-line basis.

THE STATUS LINE
The status line on your ICBM display contains several pieces of information. On the left end is an ICBM bannerlet or "text icon". To the right of this are located the following:

Your current nickname;
A MOD indicator, if you are moderator of the group you're talking in;
The group you're currently in;
The name of the server you're connected to;
A query-mode indicator, if you're currently in query mode (see /query) and space permits;
A count of unread 'write' messages for you on the server, if any and if space permits;
A 24-hour digital clock displaying local time.

If in query mode, the contents of the query indicator will vary depending on the available space on your status line. If there is sufficient space, it will display as [Q: nickname], showing who you are currently in query mode with. If there is not room for the nickname, it will display just as [QUERY], and if there is still insufficient space for that, only [Q] will be displayed. In the unlikely event that there is no room even for that, the query mode indicator will be omitted altogether. If you have unread messages on the server, the number of messages will be displayed in a counter

EDITING
The following editing keys can be used in the input window:

Up arrow
    Recall previous line from history buffer

Down arrow
    Recall next line from history buffer

Left arrow
    Move cursor one character left

Right arrow
    Move cursor one character right

Home / Ctrl-A
    Move cursor to beginning of line

End / Ctrl-E
    Move cursor to end of line

Backspace
    Delete previous character

Del key
    Delete next character

Ctrl-B
    Move cursor back one word

Ctrl-F
    Move cursor forward one word

Ctrl-W
    Delete previous word

Ctrl-U
    Delete from cursor position to beginning of line

Ctrl-K
    Delete from cursor position to end of line

Tab key
    Recall previous entry from /msg history buffer

ICBM also has several ways of recalling previously-typed messages or commands. If you type '!foo' and hit enter, the last line that you typed which began with 'foo' (if there is one) will be recalled from your history buffer and placed in the write buffer for you to resend as-is or edit further. If there is no prior matching line, nothing will happen.

If you type '^foo^bar', the last line you typed (if there is one) will be recalled to the write buffer with all instances of the first term ('foo' in this example) replaced with the second term ('bar'). If the first term is not found in the last line typed or the history buffer is empty, nothing will happen.

Both of these operators are case-sensitive.

It is possible to combine both operators in a single command with the syntax !foo^bar^baz. In this form, first the last line beginning with foo is retrieved from history, then substitution is performed on the retrieved line. If any step fails, the entire command does nothing.

For example, if a few minutes ago you had previously typed:

    The dog is stalking the cat

And then you realized that it was actually the tiger that the dog was stalking, you could type:

    !The dog^cat^tiger

After you hit enter, your input buffer would now contain:

    The dog is stalking the tiger

(The tiger would probably very shortly contain the dog, but that problem is outside the scope of this document.)

TAB HISTORY
The tab-history buffer keeps a list of the ICB users you have sent personal messages to or received personal messages from, maintained in order of most recently used. Nicks which generate a "<nick> is not signed on" error are automatically deleted from the tab history buffer. (This can be overridden by setting the variable tab_del_on_error to 0; see client variables.) Messages received while you are already in tab history composing a message will not affect the order of nicks as used by tab history.

If the tab history buffer is empty and you hit TAB on an empty input buffer, "/m " will be preloaded into your input buffer. If there are nicks saved in the tab history buffer, "/m <nick> " will be loaded into your input buffer, where <nick> is the most recently updated nick in the tab history buffer. Continuing to hit TAB will step through the tab history buffer in order of increasingly older nicks.

If there is a message in your input buffer when you hit tab, and there are nicks saved in your tab history buffer, the message content will be preserved, while nick insertion or substitution is performed as above. If the tab history buffer is empty and you hit TAB on an existing message, nothing will happen.

The tab history also supports nick autocompletion for nicks in the tab history buffer. If you type "/m al" and hit TAB, the nick will be completed with the most recently accessed nick beginning with 'al' in the tab history buffer, if present. If no matching nick is found, no replacement will be performed.

ICB COMMANDS
All ICB commands are prefixed by a / character. (This can be changed by setting a new value for the cmdchar variable (see ICBM VARIABLES)). Anything you type that is not prefixed by the current command prefix character will be sent directly to whatever group you happen to be in at the time, and will be visible to everyone in the group. If there is no-one but yourself in the group, the server will send you a warning to that effect.

Certain other characters are handled specially by ICBM. The ! and ^ characters are used for input history recall and editing. If you wish to send an open message beginning with the ! or ^ characters, you must actually begin your line with \ to escape that character. For example, if you wish to send the message:

!hola!

you must type:

\!hola!

These three reserved characters (!, ^, \) may not be used as values for cmdchar.

The following is a brief summary of a few of the most frequently used ICB commands:

/group newgroup
    Leave the group you are in and join "newgroup". If it does not exist, it will be created and you will become its moderator. You can abbrevtate group as /g.

/nick newname
    Change your nickname to "newname". 'name' is a synonym for 'nick'. The command can be abbreviated to /n.

/msg person message......
    Sends a private message to "person". The message cannot be read by any other ICB user. This command can be abbreviated to /m. Note that it is normally considered bad ICB etiquette to paste private messages to an open group, although there are exceptions (for instance, if you are being sent offensive private messages by a user in that group).

    ICBM extends the /msg command to allow you to send the same private message to multiple users simultaneously by separating their nicks by commas:

    /msg person1,person2,person3 message .....

/who group
    Lists the users currently in "group". If the group is omitted, lists all users in visible groups on the current ICB server. Use /who . to see who is in the current group. Can be abbreviated to /w.

/echoback off | on | verbose
    This command (which defaults to off) tells the ICB server whether to send you back copies of your own public and private messages. It is similar to ICBM's echo_outgoing feature (see ICBM VARIABLES), except that echo_outgoing displays what you actually typed, while echoback displays your message as the server formatted it (and hence as the recipients will see it). You will probably not want to use both this and echo_outgoing at the same time.

    The settings for this command are as follows:

      off      Server sends none of your messages back to you
      on       Server sends you your own public messages
      verbose  Server sends you your public and private messages

    Note that if you use echoback, your own messages echoed back to you from the server will go into the incoming message log, and will be redisplayed when you use the /replay command. Outgoing messages displayed by ICBM's echo_outgoing feature are not saved in the message log, and will not be replayed.

/quit
    Disconnects from the server and quits your ICB session. Unlike CICB, ICBM does not allow /quit to be abbreviated to /q, because it's too easy to accidentally hit /q when you meant to hit /w. If you feel confident, feel free to alias it (see /alias, below).

    If you attempt to quit while still mod of the group you are in, ICBM will issue a one-time warning. This warning can be disabled by setting the modwarn variable to 0.

There are many more ICB commands. The exact list of commands supported by a given server varies from one server to the next. To get a full list of commands supported by a given server, as well as their possible options (many commands have numerous possible options), try one of the following commands:

/help
    Gets a brief summary of the major commands supported by the ICB server

/s_help
    Gets a detailed listing of ICB server commands and options

ICBM COMMANDS
ICBM supports the following builtin commands in addition to the regular ICB command set:

/query person
    This is similar to cicb's '/oset personalto person' function, but simpler and more flexible. It causes all text you paste or type, unless explicitly messaged to someone else with /msg, to be sent as a private message to the person specified in your most recent /query command.

    As with the /msg command, ICBM allows you to specify a comma-separated list of nicks in a /query command:

    /query person1,person2,person3

    To unset query mode, just type /query with no arguments. (Most IRC users should be immediately familiar with this command's operation.)

/alias command othercommands
    Registers 'command' as an alias that will be expanded to 'othercommands' when used. For example:

    /alias pw msg server mypassword

    The /alias command will not allow you to use key builtin commands (for instance, alias, delcmd, set and exit, among others) as aliases. It will also not allow you to create an alias which begins with itself, such as:

    /alias bark bark Ploogie!

    as this would lead to infinite recursion during alias expansion. It is, of course, possible to set up alias loops which would lead to infinite recursion, as in the following example:

    /alias bark howl

    /alias howl bark

    However, you're pretty unlikely to do this by accident, and if you intentionally choose to go shoot yourself in the foot, well .... be my guest, it's your privilege.

/unalias alias
    Unregisters an alias created with /alias.

/correct 'pattern' 'replacement'
/correct /pattern/replacement/
    Registers replacement as a send-time typing correction for pattern in open messages, private messages and server /writes. This is used to automatically correct your own most common typos. Both the pattern and the replacement string may contain whitespace. The pattern and replacement string must either both be delimited by single quotes, or by slashes as shown above. All instances of the pattern in the input will be replaced.

    /correct ' teh ' ' the '

    /correct / teh / the /

    The /correct command will not allow you to correct a pattern to something which contains the original pattern, such as:

    /correct 'bark' 'we bark'

    as this could lead to infinite recursion during correction. However, it is not possible for ICBM to predict all possible corrections which could cause recursion.

    Both the pattern and the replacement may also contain perl regular expression terms, as in the following examples:

    To correct 'teh' to 'the', only as a complete word:

    /correct '\bteh\b' 'the'

    or

    /correct /\bteh\b/the/

    To correct 'teh' to 'the' and 'Teh' to 'The', as a whole word only:

    /correct '\b([Tt])eh\b' '$1he'

    or

    /correct /\b([Tt])eh\b/$1he/

    You can use any Perl regular expression construct in your corrections. If you aren't familiar with Perl regular expressions and you're on a Unix or Unix-like system, try reading the following man pages:

    man perlrequick
        Perl regular expressions quick start

    man perlretut
        Perl regular expressions tutorial

    man perlre
        Perl regular expressions, "the rest of the story"

    Be careful when adding send-time typo corrections. ICBM will not prevent you from shooting yourself in the foot with this feature.

    Autocorrection can be disabled on a line-by-line basis by beginning the line with the characters &&. These characters, and any following whitespace, will be stripped from that is actually sent.

    /m alaric teh foo sends the corrected "the foo", given the corrections above. /m alaric && teh foo actually sends "teh foo" exactly as typed.

    If you actually WANT to send text beginning with &&, use a \ to escape the leading &:

    /m alaric \&& teh foo sends "&& the foo"

/uncorrect 'pattern'
/uncorrect /pattern/
    Unregisters a correction defined with /correct.

/delcmd command
    Deletes a user-defined command from ICBM's command space. This is useful if you've loaded a script that turns out to contain a broken command, or if you unintentionally defined a scripted command that replaces a standard ICB command that you just realized you need.

/delhook type hook
    Deletes a user-defined hook from ICBM (see HOOKS). Useful to disable a hook that's not working as anticipated.

/encryption on|off
    The encryption command interactively enables or disables encryption (if encryption is available).

    See ENCRYPTION for further details.

/exit
    ICBM provides /exit (which can be abbreviated to /x) as a synonym for /quit. /exit can be abbreviated to /x.

/grep /pattern/
    Replays messages in the history buffer which match the regular expression /pattern/. Matching is case sensitive by default; use /pattern/i to obtain a case-insensitive match. While replaying messages, the global variable $replaying is set to 1; this enables hook functions to detect when replay is active and possibly choose not to trigger.

/hilight nick [nick ...]
    Adds nicks to the list of nicks from which ICBM will highlight personal messages. Use this to emphasize personal messages from people whose messages you particularly don't want to miss.

/unlight nick [nick ...]
    Removes nicks from the list of nicks to be highlighted.

/load scriptfile
    Instructs ICBM to load a file containing user-defined scripting functions and data in Perl (see SCRIPTING). Relative pathnames passed to /load (pathnames that do not begin with /) are assumed to be relative to $DATADIR unless present in the current directory.

/loadhook hookfile
    Instructs ICBM to load a file containing user-defined hook functions in Perl (see SCRIPTING). Relative pathnames passed to /loadhook (pathnames that do not begin with /) are assumed to be relative to $DATADIR unless present in the current directory.

/out message
    Prints the specified message to the output window. This command is mainly useful in scripts.

/replay [[count [start]] [nick1 [nick2 nick3...]] =item /replay [[starttime [endtime]] [nick1 [nick2 nick3...]]
    Replay the last <count> incoming messages. If <count> is not specified or exceeds the number of lines in the history buffer, the entire buffer will be replayed. If both <count> and <start> are specified, then a block of <count> messages starting <start> messages ago will be replayed. If <count> is greater than <start>, <start> will be ignored. For example:

    /replay 50 100

    would replay 50 messages starting 100 messages ago.

    In the second form, instead of message counts and offsets (which can be confusing), icbm replays messages received between a specified start and end time (hour:minute) within the preceding 24 hours. For example:

    /replay 13:00 14:00

    would replay messages received between 1PM and 2PM local time. endtime is allowed to be in the future; starttime must be in the past. If endtime is greater than or equal to either starttime or "now", it is presumed to refer to the previous day. Thus:

    /replay 18:00 18:00

    would replay messages from a 24-hour period.

    NOTE: ICB allows user nicks to be composed entirely of digits. If you attempt to replay messages from a user whose nick is numeric, ICBM would naturally be unable to tell the nick from a message count. Since this is likely to be a rather rare case, this problem is solved by escaping numeric nicks. Thus:

    /replay 50 \666

    would replay messages from user 666 in the last 50 messages.

    The /replay command allows extensive filtering of which messages are replayed. There are three filtering methods, any or all of which may be combined in a single command.

    Explicit include lists
        If one or more nicks are listed following the /replay command, only messages from those nicks will be included in the replay output.

        Example: /replay tom dick harry

    Exclude lists
        ICBM can be told not to display messages from certain nicks by preceding those nicks with a minus character.

        Example: /replay -dick -jane

    Message class filtering
        ICBM can filter replayed messages by packet class. There are two possible syntactical ways to specify message class filtering. The first is to simply list the desired message classes, preceded by a + symbol:

        /replay +open +msg

        The second form combined desired classes into a comma-separated class list:

        /replay +class=msg,open,status

        Supported message classes for class filtering are: open, msg, status, alert, error, output.

    For compatibility with older ICB clients, this command may also be invoked as /display.

/set variable value
    Use set to change the value of client variables such as cmdchar (see below).

/setcolor name fg [bg [bold] [reverse]]
    Use setcolor to dynamically change color settings. This is useful when you're trying to fine-tune your color settings. Color setting name (from the list above) and foreground color are optional; you may also specify background color, and bold and/or reverse. You must specify a background color if you wish to specify bold and/or reverse. Color changes made with setcolor take effect immediately; all affected text onscreen will immediately update to the new setting, although if you change bold or reverse attributes assocated with a color setting, the attributes of accected onscreen text will not change dynamically along with the color. This can result in an unexpected text appearance temporarily.

    All parameters are case-insensitive.

/setup nick
    The setup command initiates a handshake with nick's client to establish a shared session key for client-to-client encryption of personal messages. In order to use this command you must have encryption set to 1 in your defaults file, you must have all the required Perl modules installed, and the other user must be using an ICB client that supports ICBM-style client-to-client encryption.

/revoke nick
    The revoke command is the reverse of setup. It revokes your session key for nick and sends nick's client a message to revoke his session key for you.

    See ENCRYPTION for further details.

/show aliases|corrections|hilights
    This command allows you to view the current contents of client data lists in ICBM. You can currently use it to list defined aliases (see /alias, defined corrections (see /correct), and the list of nicks to be hilighted (see /hilight).

    /show aliases replaces the former /aliases command.

/timestamps on|off
    This command turns timestamping on or off. When timestamping is on, incoming message packets will be displayed prefixed with the time the packet was received, in 24-hour HH:MM:SS format. (This format may be changed if desired by changing the timestampformat variable.) Output of /who commands and client-side command output is not timestamped. Replayed packets are timestamped correctly with the time they were originally received, even if timestamping was not active when the packet was received.

/urls list|drop|purge
    This command manipulates the URL list maintained by ICBM's internal URL grabber. (This grabber used to be an external sample script that illustrated the use of hook_openmsg and hook_privmsg to implement a grabber, but was moved into the core due to problems with cross-thread variable scoping encountered with the external implementation.)

    Used without arguments, /urls simply lists the current contents of the list. /urls list with no other arguments also has this effect. /urls list foo bar baz lists all URLS containing one or more of the strings foo, bar, baz. /urls drop foo bar baz deletes all URLs containing one or more of the strings foo, bar, baz from the list. /urls purge completely clears the list. clear is a synonym for purge.

    You can add any number of extension commands to these via scripting (below). You can also use scripting to redefine the behavior of any existing command, with the exception of defined ICBM builtins. Replacing builtins could potentially leave you with an unusable client.

LOGGING
ICBM has the capability to log your sessions. This is accomplished using the /log command. By default, ICBM will log (when logging is active) to $HOME/ICBM.log, but any alternate logfile can be specified, and the default location can be changed by reassigning the $deflogfile variable.

The /log command has three forms:

/log start
    Starts logging to the default logfile specified by $deflogfile.

/log start logfile
    Starts logging to the specified by log file.

/log stop
    Closes the log file and stops logging.

If you issue a /log start while logging is already active, the currently-open log file will be closed and the new log file (which may be the same file) will be opened.

Any file in any directory may be used for logging, provided the directory is writeable by your real or effective UID, and the file either does not exist or is a normal file writeable by your real or effective UID. If the file does not exist, it will be created. If no path for the logfile is specified, ICBM will assume the file is to be opened (or created) in your home directory. All log files are opened in append mode.

ICBM makes no attempt to verify that the specified file is a plain ASCII text file; be careful.

In ICBM version 1.4.5 and later, the log_start() function can be invoked in the ICBM startup commands file, and ICBM will wait until logging is actually running to open the log.

REMOTE CONTROL
ICBM has a capability to accept input via a named pipe, or FIFO. All text sent to this FIFO will be handled by ICBM exactly as though it had been typed in the input window, with the exception of the /exit command (or the synonyms /quit or /x), which will be ignored if sent to the FIFO. You can doubtless easily find a way to circumvent this simple filter, but doing so may cause your ICBM session to hang or otherwise behave in an unstable fashion. No bragging points are awarded for shooting yourself in the foot, so let's just not do it, OK?

The default location of the FIFO is $datadir/ICBM.nnn, where nnn is the PID of the ICBM process.

WARNING!!! Use this feature with caution. Abuse of this feature to dump vast quantities of program output into an ICBM session is likely to get you at the very least booted from the group you're in, and may possibly get you -- or your entire site -- banned from that ICB server.

PAGING
ICBM can either display output continuously, or keep a count of lines and pause after each 'page' of a specified size. When the set pagesize is reached, output will stop, incoming packets will be queued, and the user will be prompted to press Enter to continue. Normal commands may still be entered at this prompt, and local command output will be displayed, though any remote responses will be queued in the buffer along with all other incoming traffic. The pagesize may be changed, or paging disabled, while paused. Timestamps of queued packets are preserved.

Paging is managed using the B/pagesize> command. Setting pagesize to 0 (the default) disables paging. Pagesize may be set to any non-negative integer value. (Reals will be rejected as non-numeric.) The following examples are valid:

/pagesize 50
    Sets page size to 50 lines.

/pagesize 0
    Turns off paging.

/pagesize
    Displays the currently-set pagesize.

ENCRYPTION
ICBM v1.4.0 and later supports encryption of personal messages between ICBM and other ICB clients which implement ICBM's client-to-client encryption scheme. This encryption uses the Blowfish cipher with a per-user, per-session shared key generated by taking a Base64-encoded SHA1 hash of a randomly-chosen line from message history. Session keys are exchanged encrypted with a one-time key generated using Diffie-Hellman key exchange. Interoperability of this key exchange relies upon all clients using the same initialization table of 48-bit primes.

To initiate encryption to another user, enter the command /setup USER. This will begin the key negotiation handshake with the remote user. If the handshake succeeds, ICBM will display the following message within a few seconds:

[=SECURE=] Session key for user %s established

This indicates that both you and the remote user now have a copy of the valid session key. This message will also be displayed when a remote user successfully establishes a session key with your client. This key is valid between your two clients as long as both clients maintain the same session and the same nick.

If you receive the following warning message:

[=Warning=] Cannot setup: user USER has encryption disabled

then your remote user's client supports encryption, but the user has it disabled.

If there is no result within a few seconds, or if you receive a puzzled response from the user, the user's client does not support encryption.

Once a session has been set up, all private messages between the two clients will automatically be encrypted with the last known good key. If one client changes nick, while both clients are in the same group, ICBM will react to the nick-change message and update its session key table. If one client makes a nick change that is not visible to the other, or signs off and logs back on, the shared key will become invalid. Sending a message encrypted using an invalid key will result in the following message on the sender's console:

[=Warning=] Message failed (stale key): Set up new key for user USER

And on the recipient's console:

[=Warning=] Unable to decrypt encrypted packet from USER : No session key

If this occurs, a new session key must be negotiated using the /setup command. Alternately you can choose to end the encrypted session using /revoke nick. This command will cause both your and the other user's keys for the session to be cancelled.

Encryption can be turned on or off during a session, if available, using the /encryption on|off command. This is equivalent to /set encryption 1|0.

See the file README.ENCRYPTION for additional information.

ICBM VARIABLES
Many aspects of ICBM's internal behavior are controlled by variables which can be set either in the startup file using the set() function, or interactively using the /set command. The variables available, their defaults, and their effects, are as follows:

beep_on_error (default: 1)
    Controls whether ICBM emits an audible beep on certain types of input errors. Set to 0 to disable.

beeps (default: 1)
    Controls whether ICBM emits an audible beep when you receive a beep message from the server. Set to 0 to disable.

cc_msg_lists (default: 0)
    Controls whether all recipients of a message with private multiple recipients receive a list of the persons to whom the message was sent. Set to 1 to enable.

cmdchar (default: /)
    The character used to prefix ICB/ICBM commands. May be set only to a single character, which may not be one of the following reserved characters: \ ^ !

deflogfile (default: $HOME/ICBM.log)
    Controls the default location of the ICBM log file.

echo_outgoing (default: 1)
    Controls whether outgoing open and private messages that you type are echoed to the output window. (You will probably not want to use both this and echoback.) Set to 0 to disable.

logtimeformat (default: "%H:%M:%S %Z %b %d %Y")
    This is the format string used to timestamp log open and close events. It may be set to any format string valid for strftime(). Changes to logtimeformat take effect immediately.

modwarn (default: 1)
    Controls whether ICBM issues a one-time warning if you attempt to quit while still moderator of the group you are in. Set to 0 to disable.

report_correction_set (default: 1)
    Controls whether ICBM displays a confirmation message on loading corrections. Set to 0 to disable.

report_load_success (default: 1)
    Controls whether ICBM displays a status message to report successful loading of scriptfiles loaded with the load command. Set to 0 to disable.

report_load_warnings (default: 1)
    Controls whether ICBM displays a warning message if it is unable to locate a file in a load command. Set to 0 to disable.

report_load_errors (default: 1)
    Controls whether ICBM displays an error message if an error occurs while loading a file. Set to 0 to disable.

report_url_capture (default: 1)
    Controls whether ICBM displays a message when it detects and stores a URL. Set to 0 to disable.

readhistsize (default: 500)
    Controls the maximum size of ICBM's history buffer for incoming message packets. Set to 0 to disable message history.

tab_del_on_error (default: 1)
    Controls whether ICBM deletes nicks from tab history if they generate a 'not signed on' error. Set to 0 to disable.

timeformat (default: "%H:%M:%S")
    This is the format string used to display the time in the status bar clock. It may be set to any format string valid for strftime(). Changes to logtimeformat take effect immediately.

timestampformat (default: "%H:%M:%S")
    This is the format string used to timestamp message packets. It may be set to any format string valid for strftime(); however, it is recommended that you keep it short. Changes to timestampformat take effect immediately.

writehistsize (default: 500)
    Controls the maximum size of ICBM's history buffer for typed commands and messages. Set to 0 to disable typing history.

writesize (default: 5)
    This variable controls the number of lines set aside in your terminal for the input window. It CAN ONLY BE SET IN THE datadir/settings FILE, and cannot be changed while ICBM is running (or, more accurately, changing it while ICBM is running has no effect).

More variables may be added in future as necessary.

SCRIPTING
ICBM can be extended by user-side scripting in Perl. The script file does not need to begin with a #!/usr/bin/perl, but it does no harm if it does.

Several commands exist in ICBM to facilitate scripting. The set is small, but versatile. These commands are explained below.

addcmd()
    addcmd("news");

    Used to register a user-defined command in ICBM's command space.

alias()
    alias(".", "who .");

    Creates an alias, just like the /alias command.

unalias()
    unalias(".");

    Unregisters an alias, just like the /unalias command.

delcmd()
    delcmd("news");

    This, exactly like the /delcmd command, unregisters a user function from the command space.

get_group()
    my $group = get_group();

    Returns the name of the current group to a script.

get_mod()
    if (get_mod()) { ..... }

    Returns a binary flag indicating whether you are mod of the current group or not.

get_nick()
    my $nick = get_nick();

    Returns your current active nick to a script.

get_urls()
    my @urls = get_urls();

    Returns the list of URLs captured by the internal URL grabber for use by userside scripts.

hilight()
    hilight('larry', 'moe', 'curly');

    Adds nicks to the hilight list, exactly like /hilight.

unlight()
    unlight('larry', 'moe', 'curly');

    Removes nicks from the hilight list, exactly like /unlight.

docommand()
    docommand("/m server news 8");

    This function allows any command which can be typed at the keyboard to be embedded in a script. This command enables the user to write scripts that interact with the server and client using any defined ICBM command or alias, without having to understand the internal workings of ICBM, the server, or the ICB protocol.

load()
    load('more_commands');

    Just like the /load command, this causes ICBM to load a specified script file.

loadhook()
    loadhook('my_hooks');

    This causes ICBM to load a file containing hook functions. load() and <loadhook()> are not interchangeable, as they load the files into the context of different threads.

out()
    out ("You can't get the wood, you know.");

    Displays a message in the read window, just like the /out command.

set()
    set ('modwarn', 0);

    Used to change client variables from a script.

set_color()
    set_color ('output', 'green');

    set_color ('output', 'green', 'magenta', 'bold', 'reverse');

    Changes a color setting, like the setcolor command.

HOOKS
In addition to the above scripting functions, ICBM provides a range of different hooks which allow scripted actions to be triggered by a variety of ICB events. Two functions exist for managing hooks from a script:

addhook()
    addhook ('connect', 'register');

    The addhook() function takes two operands, an event class and a function name, and adds the specified function to the list of functions called by ICBM when an event of that class occures. The function will be passed a single string containing the entire contents of the ICB message packet which triggered the event. It is your responsibility to decide what to do based on the contents of the packet.

    A warning will be issued if the event class is unknown.

delhook()
    delhook ('connect', 'register');

    The delhook() function unregisters a specified hook function. delhook() is to addhook() exactly as delcmd() is to addcmd().

    A warning will be issued if the event class is unknown or if the hook function is not found.

Script functions are passed an array containing the data fields of the ICBM message packet. Depending on the packet type, there may be from 0 to 8 fields. It is the responsibility of the hook function to parse these fields and determine what to do with them. MOST packets will contain only two fields; in this case, argument 0 (accessed as $_[0]) will contain either the name of the sender of an open or private message, or a specific message type string such as 'Notify-On' in the case of a server message, and argument 1 (accessed as @_[1]) will contain the actual text of the message. See the provided sample_hooks file for example hook functions, including a show_packet function that could be used to display all the fields of the function that triggered the packet. A hook function could even call this function internally by including the following line:

    show_packet(@_);

The event classes currently defined are as follows (not in any particular logical order):

connect
    Called exactly once when your client initially connects to the server. This is one of only two hook types that does NOT pass a message packet (the other is modwarn).

openmsg
    Called whenever your client receives an open message.

privmsg
    Called whenever your client receives a private message.

    NOTE: The sender nick in private messages will be prefixed with an asterisk (e.g, *fred instead of fred). This enables a single hook function to be used for both open and private messages and to be able to tell which of the two types of event triggered it. If you're writing a hook function that will automatically reply to private messages, remember to strip the asterisk off.

newpriv
    Called whenever your client receives a private message that begins a conversation (i.e, from a user not already in the tab history list).

memo
    Called whenever someone sends you a /write memo while you are logged in, or whenever there is one or more /write memos already waiting for you when you log in.

beep
    Called whenever another ICB user beeps you.

ping
    Called whenever another ICB user pings your client to see how much lag time exists between your client and theirs.

group
    Called whenever you enter a group.

join
    Called whenever someone else enters the group you're in.

notify
    Called whenever someone you have in your notify list signs onto or off of the server (see the ICB server help, /s_help, for documentation of the notify command). It is your responsiblity to distinguish Notify-On and Notify-Off events.

modgain
    Called whenever you become the moderator of a group, including by creating a new group.

modloss
    Called whenever you lose moderatorship of a group (usually via the server's idle-mod feature).

modpass
    Called whenever you pass moderatorship of a group, or drop moderation on the group altogether.

modwarn
    Called when you attempt to exit ICBM while still moderator of a group. This is one of only two hook types that does NOT pass a message packet (the other is connect).

boot
    Called whenever someone boots you from a group.

idleboot
    Called whenever you are idlebooted from a group by the server.

error
    Called whenever the server sends you an error message packet.

alert
    Called whenever the server sends you an alert message packet.

awol
    Called when the server reports that a user you just tried to message (etc.) is no longer logged on.

nickchg
    Called when a user in the group you are in changes their nick.

rename
    Called whenever the group you are in is renamed.

status
    Called whenever the server sends you any other status packet.

trigger
    Called on ALL packets when a generic trigger event has been set (see TRIGGERS).

url Called whenever the URL grabber captures a URL token from a message packet. The hook function is sent an abbreviated packet containing only the sender name and the URL token. The hook function may be called multiple times on a given message if the message packet contains multiple detected URL tokens.

TRIGGERS
In addition to all the above, ICBM contains a mechanism for implementing generic trigger events. At present, only one trigger should be defined at a time. This mechanism allows the user to define a function which will send a command to the ICB server, wait for the server's response to that command, and then finish executing. There are a set of eight functions for using this functionality with the 'trigger' hook type referenced above:

get_trig_mask(), set_trig_mask()
    These functions set and read, respectively, the mask against which server responses should be checked by the hook function which will "catch" the trigger.

get_trig_result(), set_trig_result()
    These functions set and read, respectively, a result field which the trigger hook function can use to pass the trigger result back to the function which set the trigger.

get_trig_status(), set_trig_status()
    These functions set and read a flag used to determine whether a trigger is active and, accordingly, whether the trigger function list should be called. Functions using triggers should always clear the trigger by calling set_trig_status(0) after the desired trigger has been caught.

get_trig_action(), set_trig_action()
    These functions set and read a variable which can be used to pass an action to the trigger hook function.

The basic method which should be used to utilize generic triggers is as follows:

    Set up the trigger mask, ensure the result is set to 0, and set status to 1 to enable the trigger.

    Send the server command

    Sleep, polling the trigger result, until the trigger is caught

    Clear the trigger and resume processing.

SAMPLE SCRIPT
The following simple scripting example illustrates how to put the above functions together with ICB commands and ICBM commands to achieve a variety of results:

sub ploogie {
    my ($input) = $_[0];

    if ($input)
    {
        docommand("/msg icbm Ploogie!  $input");
        docommand($input);
        out ("We can TOO get the wood!");
    }
    else
    {
        docommand('/msg icbm Ploogie!');
        docommand('Ploogie!');
        out ("You can't get the wood, you know.");
    }
    chomp (my $date = `date`);
    out ($date);
}
addcmd ("ploogie");

setcolor ('output', 'green', 'magenta', 'bold', 'reverse');

out ("Today's date is $date, ICBM time.");

sleep (2);

setcolor ('output', 'green');

out ("My god, those colors were hideous beyond mortal imagination."); out ("Please kill yourself now as a service to humanity.");

set ('readhistsize', 750);

load ('more_commands');

If you should happen to accidentally load a function that overwrites a key built-in command that you need, you can use delcmd to delete the user-defined function and return to the built-in function. In the worst case, you can always kill ICBM, remove the offending code from your script files, and restart ICBM.

SAMPLE HOOKS
The following illustrates some basic example hook functions:

sub who {
    docommand ('/who .'); }

addhook ('group', 'who');

sub register {
    docommand ('/msg server p MYPASSWORD'); }

addhook ('connect', 'register');

sub humbug {
    my ($who, $msg) = @_;

    if ($msg =~ /^bah$/i)
    {
        docommand ('Humbug');
    }
    elsif ($msg =~ /^bah!$/i)
    {
        docommand ('Humbug!');
    }
}
addhook ('openmsg', 'humbug');

sub sample_url_hook {
    my ($who, $msg) = @_;
    show_packet(@_);
    docommand ("/msg $who You sent the URL $msg");
    docommand ("Captured URL $msg"); } addhook('url','sample_url_hook');

SAMPLE TRIGGER USAGE
The following two functions, placed in the commands and hooks files respectively, implement a single-command function to drop a zombie connection (or someone else using your nick) and recover your nick.

The triggering function:

sub reclaim {
    my $nick = $_[0];
    my $result;

# Set up the generic trigger

    set_trig_mask ("$nick .* disconnected");
    set_trig_result (0);
    set_trig_status (1);

    docommand ("/drop $nick MYPASSWORD");

# Sleep on trigger

    until (($r = get_trig_result()) =~ /disconnected|found/)
    {
        out ("Result: $r");
        sleep (1);
    }

# Clear the trigger

    set_trig_status (0);
    set_trig_result (0);
    set_trig_mask ('');

    docommand("/nick $nick");
    docommand("/m server p MYPASSWORD");
}
addcmd("reclaim");

And the trigger hook:

sub deadjim {
    my ($who, $msg) = @_;
    my $mask = get_trig_mask();

    if ($msg =~ /$mask/i || $who =~ /User not found/)
    {
        set_trig_status (0);
        set_trig_result ($msg =~ /$mask/i ? $msg : $who);
    }
}
addhook('trigger', 'deadjim');

IMPORTANT PROGRAMMING NOTE:
Because ICBM is multithreaded, you should not use FORK calls in your scripts, nor use system() calls to start external perl scripts which then FORK. Doing so may have unexpected results, including creating a rise in system load with no visible cause. It should go without saying that ICBM scripts should NEVER call exec().

COLORS
Colors are specified in $DATADIR/colors quite simply as follows:

    nickname    yellow black
    hostmask    green black
    modstar     red black bold
    userflags   red white
    idletime    cyan black bold reverse
    etc.

The supported colors and attributes are as follows: bold, reverse, black, red, green, yellow, blue, magenta, cyan, and white. All attributes should work on any terminal which supports color. The order of fields is: color setting name, foreground color, background color, bold or reverse, bold or reverse. If you wish to specify bold or reverse, you MUST specify the background color; otherwise, it can be omitted and will be assumed to be black.

The supported color settings are (not in any particular order):

    normal        "Normal" text in the ICB window
    output        Your own typing and script output
    ownmsg        Your own outgoing text, if echoback is enabled
    personal      Body of personal messages to you
    encrypted     Body text of encrypted personal and outgoing messages
    persfrom      Nickname of personal message sender
    hilight       Body of personal message from highlighted sender
    hilightfrom   Nickname of highlighted personal message sender
    who_hdr       Header lines in /who listings
    nickname      Nick of ICB user
    hostmask      ICB user's hosername and host address
    modstar       The star indicating who has mod in a group
    userflags     Unregistered or Away flags on a user
    idletime      Time since an ICB user last typed anything
    logintime     Time an ICB user last logged in
    beep          Beep message text
    beepfrom      Nickname of beep sender
    status        Status messages from the server
    alert         Alerts from the server
    error         Server error messages
    warning       Warning messages from the client (usually script-related)
    more          The "--- PAUSED: Press Enter ..." prompt if you have paging turned on
    sbrkt         Color of [ ] brackets in server messages
    abrkt         Color of < > brackets around nicks
    pbrkt         Color of <* *> brackets around /msg nicks
    statline      The ICB window status line
    debug         Output from the icb_debug() function

All color settings are case insensitive. Whitespace is not significant.

If you expect to get color and you're not, try changing your TERM setting. For instance, although most xterms support ANSI color (which is used by ICBM's non-interactive mode), curses (used by ICBM's interactive mode) generally does not believe that an xterm will support color, but if you change the TERM variable to xterm-color or color_xterm, curses will be perfectly happy with it. You can either make this change in your shell initialization files, or simply set TERM when you start icbm as in the following example:

    TERM=xterm-color icbm -g ICBM -n ICBM -color

DEPENDENCIES
ICBM should work on any threaded Perl 5.6.0 or later installation. It requires the following Perl modules for basic functionality:

    threads
    threads::shared
    POSIX
    Curses
    Config
    Getopt::Long
    Module::Load::Conditional
    Net::ICB
    Pod::Usage
    Term::ANSIColor
    Term::ReadKey

Most of these are included as standard with the Perl distribution. You will probably have to install Term::ANSIColor and Net::ICB. On Debian Linux installations, you may also need to manually install Term::ReadKey.

The following additional modules are required in order to enable encryption:

    Compress::Zlib
    Crypt::Blowfish
    Crypt::CBC
    Crypt::DH::GMP
    Digest::SHA
    MIME::Base64

These modules are conditionally loaded if all are present. If one or more is missing, none are loaded and ICBM will not permit encryption to be enabled.

The standalone primegen tool, used to generate a new table of 48-bit primes if desired, requires:

    Math::Pari
    Crypt::Random
    Crypt::Primes

ENVIRONMENT VARIABLES

ICBM_DATA
    Sets the location of ICBM's data directory, if present. The default location is $HOME/.icbm if ICBM_DATA is not set.

ICBNAME
    ICBM will honor the CICB/fnet ICBNAME variable if it is present.

FILES

$DATADIR/colors
    Client color setting file

$DATADIR/commands
    Default file for user scripts and data

$DATADIR/defaults
    Early-initialization client variables ONLY

$DATADIR/hooks
    Default file for user hook functions and data

icbserverdb
    ICB server database (compatible with cicb). May be located in any of the following locations:

        $HOME/.icbserverdb
        $DATADIR/icbserverdb
        /usr/share/icb/icbserverdb
        /usr/local/share/icb/icbserverdb
        /usr/local/lib/icb/icbserverdb
        /usr/local/lib/icbserverdb
        /usr/lib/icb/icbserverdb
        /usr/lib/icbserverdb
        ./share/icb/icbserverdb

$DATADIR/primes
    Contains the table of 48-bit primes used for Diffie-Hellman key exchange. May be located in any of the following locations:

        $DATADIR/primes
        /usr/share/icb/primes
        /usr/local/share/icb/primes
        /usr/local/lib/icb/primes
        /usr/local/lib/primes
        /usr/lib/icb/primes
        /usr/lib/primes
        ./share/icb/primes

REQUIREMENTS
ICBM requires Perl 5.6.0 or later, compiled with ithreads support; the Perl modules listed above in DEPENDENCIES, some of which may not be included with your Perl distribution; and a Curses-compatible terminal. This should not be a problem on any Unix-based platform. Usage on Windows is probably best accomplished via cygwin.

It is not believed at this time that ICBM will run using ActivePerl on Windows, as the ActivePerl install lacks both ithreads and at least one of the required modules, and correcting these deficiencies in ActivePerl is not a trivial process.

KNOWN BUGS AND DEFICIENCIES

-clear and -password
    CICB's -clear option, which sanitizes the commandline and is intended for use with the -password option (which implies -clear) is difficult to implement from a perl script, and I do not at this time know how to do it. Without -clear, -password is massively insecure, as your password is left hanging out in the ps listing for anyone on the system to see. Therefore neither -password or -clear is implemented in ICBM, since I do not have a way for ICBM to implement them securely. Workarounds or solutions for this problem are welcomed; I'd love to know how to do this in Perl.

Color in who listings
    Color attributes in WHO listings are applied to entire fields, which may be larger than the data they contain. This will be apparent only when using background colors or reverse video. This is a minor cosmetic defect only, and fixing it is a low-priority item because there are more important things needing work right now.

Text attributes do not update dynamically along with text colors
    There's nothing I can reasonably do about this. It's an artifact of the way text colors vs. text attributes are implemented in curses, and can't really be fixed without re-implementing curses.

Some failure modes can leave terminal settings disturbed
    ICBM makes every attempt to clean up after itself by issuing an 'stty sane' as the last thing it does before it exits. However, some failure modes may occur in which ICBM does not get a chance to clean up after itself. In this event, manually running 'stty sane' should restore the terminal.

SIGWINCH
    ICBM does not handle window size changes particularly gracefully. (In fact, it handles them distinctly ungracefully.) This is largely a limitation imposed by Curses.pm's implementation (or rather, non-implementation) of is_term_resized() and the KEY_RESIZE event. Workarounds or solutions for this problem are welcomed. I currently believe the problem to be insoluble because insofar as I have been able to determine, whether or not I trap SIGWINCH myself, it appears icbm never actually receives either SIGWINCH or KEY_RESIZE.

Input scrolling
    When the user types more lines of text than the input window will hold, ICBM scrolls the input window up correctly, but subsequently fails to calculate cursor position correctly and does not scroll the input window back correctly when appropriate. I haven't yet figured out why this is happening, but I suspect it's still another deficiency in Curses.pm. Solutions for this problem are welcomed. Dynamically growing the input window would be nice, but I'm beginning to strongly suspect that is yet another thing that won't work Because Curses.

Color not available on Solaris 10
    Curses color does not appear to be available through Curses.pm on Solaris 10. I don't yet know why this is, but I'm assuming that it has to do with the way libcurses is compiled on Solaris 10. I am considering this a WONTFIX at this point because, seriously, Solaris is dead. But if you have a fix, feel free to contribute it.

Unclean exit on OSX (reported by Ryan Powers) Perl reports an error "recv size: Bad file descriptor at /Library/Perl/5.8.6/Net/ICB.pm line 285" on exit when running on OSX.  I believe this bug to be fixed, but do not have an OSX machine to test on.

TODO

Implement scrolling the read window back to view previous messages (use PgUp/PgDn?) This seems to be a terminal-dependent problem that needs to be separately fixed for xterm, tmux, screen, and alacritty, and possibly each valid combination thereof.

REPORTING BUGS
Send bug reports to the author. The ICBM mailing list has been discontinued due to a combination of lack of subscribers and a surfeit of attempts to spam it.

LICENSE
ICBM is copyright (C) 2003-2022 Phil Stracchino.

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.

OBTAINING ICBM
ICBM can be downloaded from http://co.ordinate.org/icbm/ as ICBM-current.tar.gz.

AUTHOR
ICBM is written and maintained by Phil Stracchino (icbm@co.ordinate.org), based upon ideas from Roger Espel Llima's sirc IRC client and John Vinopal's Net::ICB module. The scripting code in particular was heavily influenced by sirc.