Multi user chat - Version 1.2
D'Arcy J.M. Cain
darcy at druid.uucp
Sun Oct 28 07:37:09 AEST 1990
-----------------------------------------------------------------------
NOTE: There was a n error in the first post this morning. If you got
it before the cancellation please ignore it. This is the correct
posting. Sorry for any inconvenience.
-----------------------------------------------------------------------
Well here it is. This time the header file is included. I also dropped
the getopt.h and process.h include statements and just included the
relevant prototypes and extern declarations where required. Hopefully
this will avoid some problems that people have been having.
You will need an ANSI compiler to compile this or else a filter such as
unprotoize in order to compile this.
This has been tested on ESIX 3.2 Rel D compiling with GNU C. I
used the standard libraries but the header files are a modified
version of the ones that came with the development set. I believe
that the result is a fairly compliant ANSI environment but if you
have an ANSI compiler that chokes on this I would certainly like
to hear from you.
I would also like to get your comments on the package itself. If
you have any suggestions for added features or improvements please
send them along. I hope to have a network (TLI) version soon. I
would create a sockets version but I don't have any experience in
that area or a system to play with. If anyone wants to create a
chc_sock.c and chs_sock.c file I will gladly include it in the
distribution.
Enjoy.
#!/bin/sh
# This is a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 10/27/1990 20:20 UTC by darcy at druid
# Source directory /usr/darcy/work/chat
#
# existing files WILL be overwritten
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 9540 -rw-r--r-- chat.c
# 4071 -rw-r--r-- chatter.c
# 1586 -rw-r--r-- chc_msg.c
# 2340 -rw-r--r-- chs_msg.c
# 1164 -r--r--r-- chat.h
# 537 -r-xr--r-- lchat
# 682 -r-xr-xr-x chatyell
# 2516 -r--r--r-- chat.readme
# 520 -r--r--r-- chat.make
#
# ============= chat.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'chat.c' &&
X /*
X
chat
Written by D'Arcy J.M. Cain
All rights reserved
X
This is the front end to the chatter program. It is run by any number
of users who wish to communicate conference style with each other. The
chatter program serves each user.
X
Permission is hereby granted to freely copy and redistribute this
software, provided that the author is clearly credited in all
copies and derivations. This software is provided ``As Is'' and
without any express or implied warranties.
X
*/
X
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curses.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include "chat.h"
X
char chat_rcsid[] = "$Id: chat.c,v 1.2 90/10/26 19:55:16 darcy Exp Locker: darcy $\b ";
X
extern char chc_rcsid[];
X
#ifndef NO_CHG_NAME
static char *options = "hn:f:";
#else
static char *options = "hf:";
#endif
X
extern int getopt(int argc, char **argv, const char *opts);
extern int optind, opterr;
extern char *optarg;
X
extern int execlp(const char *path, const char *arg0, ...);
extern int fork(void);
extern int wait(int *stat_loc);
X
static FILE *cap_file = NULL;
static WINDOW *disp, *inp;
X
#ifdef HALFDELAY_BROKEN
int chat_suspended = 0;
#endif
X
void cleanup(int sig) /* come here on just about any signal */
{
X while (chk_q()) /* clean up your own mess */
X ;
X
X if (cap_file != NULL)
X fclose(cap_file);
X
X chc_send("x");
X
X mvwprintw(inp, 1, 1, "%-77s", " So long... It's been nice chatting");
X wrefresh(disp); /* display any leftovers */
X wrefresh(inp); /* display polite message */
X
X delwin(disp);
X delwin(inp);
X endwin();
X ch_close();
X exit(0);
}
X
void disp_str(char *str) /* add latest string to list just above box */
{
X scroll(disp); /* make room for it first */
X mvwprintw(disp, LINES - 5, 0, "%s", str);
X
X if (cap_file != NULL) /* save to file if it is open */
X fprintf(cap_file, "%s\n", str);
}
X
static int need_to_refresh = 0;
X
int chk_q(void)
{
X char msgbuf[256];
X
X if (ch_get(msgbuf))
X {
X disp_str(msgbuf); /*let user know what chatter has to say */
X
X if (*msgbuf == 'e') /* is chatter telling us to get lost? */
X {
X wrefresh(disp); /* display anything pending */
X cleanup(0); /* take the Big Sleep */
X }
X
X need_to_refresh = -1;
X return(1); /* let caller know */
X }
X
X return(0); /* nothing happened */
}
X
#ifndef NO_SH_ESC
static void run_command(char *s)
{
X int status, pid, w, tty;
X void (*istat)(), (*qstat)();
X
X if ((tty = open("/dev/tty", 2)) == -1)
X {
X fprintf(stderr, "Can't open /dev/tty\n");
X return;
X }
X
X if ((pid = fork()) == 0)
X {
X close(0); dup(tty);
X close(1); dup(tty);
X close(1); dup(tty);
X close(tty);
X execlp("sh", "sh", (*s ? "-c" : NULL), s, NULL);
X exit(0); /* note: We don't care about failure here */
X }
X
X close(tty);
X istat = signal(SIGINT, SIG_IGN);
X qstat = signal(SIGQUIT, SIG_IGN);
X
X while ((w = wait(&status)) != pid)
X if ((w == -1) && (errno != EINTR))
X break;
X
X signal(SIGINT, istat);
X signal(SIGQUIT, qstat);
}
#endif
X
void help(void)
{
X WINDOW *w;
X int k;
X static char *help_msg[] = {
X "CHAT - multi user conference utility",
X "Written by D'Arcy J.M. Cain (darcy at druid.uucp)",
X "Copyright 1990 - All rights reserved",
X "$Revision: 1.2 $\b " + 1,
X "",
X "chat commands consist of a slash (/) followed by a command",
X " ? this Help screen",
#ifndef NO_SH_ESC
X " ! shell Escape",
#endif
X " c Change channel i.e: \"/c3\" - change to channel 3",
X " Note: \"/c*\" will change to first empty channel",
X " h Same as ?",
#ifndef NO_CHG_NAME
X " n change Name to following string",
#endif
X " r Redraw screen",
#ifndef NO_SHOW_USERS
X " s Show current users using chat",
#endif
X " x eXit from chat",
X "",
X " Hit a key to continue ..."
X };
#define HELP_SZ (sizeof(help_msg)/sizeof(char *))
X
X w = newwin(HELP_SZ + 3, 71, 1, 3); /* get a new window */
X box(w, 0, 0); /* and box it */
X
X for (k = 0; k < HELP_SZ; k++) /* display the help screen */
X mvwprintw(w, k + 1, 3, "%s", help_msg[k]);
X
X wrefresh(w); /* show the screen */
X
X while (wgetch(w) == ERR)
X ; /* wait for keystroke */
X
X delwin(w); /* clear the window */
X touchwin(disp); /* update display window */
X wrefresh(disp); /* get everything back in sync */
X wrefresh(inp);
}
X
int main(int argc, char **argv)
{
X int c;
X char entry[512], *ptr = NULL, *ptr1, msgbuf[256];
X
X if ((ptr1 = ch_init()) != NULL)
X {
X perror(ptr1);
X return(1);
X }
X
X /* curses stuff */
X initscr();
X nonl();
X noecho();
X cbreak();
#ifndef HALFDELAY_BROKEN
X halfdelay(20);
#endif
X
X /* make sure we always exit through cleanup */
X signal(SIGINT, cleanup);
X signal(SIGABRT, cleanup);
X signal(SIGQUIT, cleanup);
X signal(SIGKILL, cleanup);
X signal(SIGTERM, cleanup);
X
X disp = newwin(LINES - 4, COLS, 0, 0); /* conversation window */
X idlok(disp, TRUE);
X scrollok(disp, TRUE);
X
X inp = newwin(3, COLS, LINES - 4, 0); /* input window */
X box(inp, 0, 0);
X
X mvwprintw(inp, 1, 1, "-> "); /* prompt string */
X
X while ((c = getopt(argc, argv, options)) != -1)
X {
X switch (c)
X {
X case '?':
X default:
X sprintf(entry, "%s: Invalid option %c", argv[0], c);
X disp_str(entry);
X
X case 'h':
X sprintf(entry,
#ifndef NO_CHG_NAME
X "Usage: %s [-h] [-c channel] [-n name] [-f file]",
#else
X "Usage: %s [-h] [-c channel] [-f file]",
#endif
X argv[0]);
X disp_str(entry);
X cleanup(0);
X break;
X
#ifndef NO_CHG_NAME
X case 'n':
X ptr = optarg;
X break;
#endif
X
X case 'f':
X if ((cap_file = fopen(optarg, "a")) == NULL)
X {
X sprintf(entry, "Can't open log file: %s", sys_errlist[errno]);
X cleanup(0);
X }
X break;
X }
X }
X
X disp_str("chat - multi user conferencing utility"); /* signon string */
X disp_str("Written by D'Arcy J.M. Cain");
X disp_str("Copyright 1990 by D'Arcy J.M. Cain - All rights reserved");
X disp_str("$Revision: 1.2 $\b " + 1);
X disp_str("");
X
X /* open chat link */
X ch_init();
X sprintf(entry, "o%s", (ptr == NULL) ? cuserid(NULL) : ptr);
X chc_send(entry);
X sleep(1); /* messages are not FIFO */
X
X disp_str("Enter /h or /? for help");
X disp_str("");
X wrefresh(disp);
X
X ptr = entry;
X chc_send("s"); /* get list of current users */
X
X for (;;) /* loop till the cows come home */
X {
X while (chk_q())
X ;
X
X if (need_to_refresh)
X wrefresh(disp); /* refresh display if necessary*/
X
X wrefresh(inp); /* refresh this to place cursor */
X
X if ((c = wgetch(inp)) != ERR); /* if got a character (not timed out) */
X {
X if (c == 4)
X cleanup(0); /* end of session ? */
X
X if (c == '\r') /* end of line ? */
X {
X *ptr = 0;
X
X if (*entry == '/') /* command? */
X {
X switch (entry[1])
X {
X case 'v': /* file versions. undocumented */
X disp_str(chat_rcsid + 1);
X disp_str(chc_rcsid + 1);
X chc_send("v");
X break;
X
X case '?': /* request for help */
X case 'h':
X help();
X break;
X
#ifndef NO_SH_ESC
X case '!': /* shell escape */
X ptr = entry + 2;
X while (isspace(*ptr))
X ptr++;
X
#ifdef HALFDELAY_BROKEN
X chat_suspended = 1;
#endif
X endwin();
X run_command(ptr);
X printf("\n[Press 'Enter' to continue ...]");
X
X while (gets(entry) == NULL)
X ;
X
X doupdate();
#ifdef HALFDELAY_BROKEN
X chat_suspended = 0;
#endif
X break;
#endif
X
X case 'l': /* redraw screen */
X case 'r':
X clearok(disp, TRUE); /* update display window */
X clearok(inp, TRUE); /* update input window */
X wrefresh(disp); /* redraw both windows */
X wrefresh(inp);
X clearok(disp, FALSE); /* reset display window */
X clearok(inp, FALSE); /* reset input window */
X break;
X
#ifndef NO_CHG_NAME
X case 'n': /* these are passed to chatter */
#endif
#ifndef NO_SHOW_USERS
X case 's':
#endif
X case 'c':
X ptr = entry + 2;
X while (isspace(*ptr))
X ptr++;
X sprintf(msgbuf, "%c%s", entry[1], ptr);
X chc_send(msgbuf);
X break;
X
X case 'x': /* exit from chat */
X case 'q': /* for Dennis Breckenridge :-) */
X cleanup(0);
X break;
X
X default:
X beep();
X }
X }
X else if (*entry) /* else send it if not blank */
X {
X sprintf(msgbuf, "m%s", entry);
X chc_send(msgbuf);
X }
X
X ptr = entry; /* reset input box */
X mvwprintw(inp, 1, 1, "%77s", "");
X mvwprintw(inp, 1, 1, "-> ");
X }
X else if (c == '\b') /* take care of backspaces */
X {
X if (ptr != entry)
X {
X wprintw(inp, "\b \b");
X ptr--;
X }
X }
X else if (c == '\t') /* expand tabs */
X {
X ptr1 = ptr + 8 - ((ptr - entry) % 8);
X while (ptr != ptr1)
X {
X *(ptr++) = ' ';
X waddch(inp, ' ');
X }
X }
X else if ((c >= ' ') && (c < 0x7f)) /* otherwise if printable */
X {
X if ((ptr - entry) > 62) /* time for word wrap? */
X {
X *(ptr++) = c; /* don't lose latest char */
X *ptr = 0; /* terminate string */
X
X while (!isspace(*ptr)) /* find latest space */
X {
X if (--ptr == entry) /* special case - no spaces */
X {
X ptr += strlen(entry);
X *(ptr + 2) = 0;
X break;
X }
X }
X
X *(ptr++) = 0; /* change space to zero */
X sprintf(msgbuf, "m%s", entry);
X chc_send(msgbuf);
X strcpy(entry, ptr); /* change string to leftover */
X ptr = entry + strlen(entry);
X mvwprintw(inp, 1, 1, "%77s", ""); /* clear input box */
X mvwprintw(inp, 1, 1, "-> %s", entry); /* print string */
X }
X else
X waddch(inp, (*(ptr++) = c)); /* print character */
X }
X }
X }
}
SHAR_EOF
chmod 0644 chat.c ||
echo 'restore of chat.c failed'
Wc_c="`wc -c < 'chat.c'`"
test 9540 -eq "$Wc_c" ||
echo 'chat.c: original size 9540, current size' "$Wc_c"
# ============= chatter.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'chatter.c' &&
/*
X
chatter
server process for multi-user chat
Written by D'Arcy J.M. Cain
West Hill, Ontario
darcy at druid.UUCP
All rights reserved
X
This is the server for the chat program. It handles various
requests and sends messages to the users of chat.
X
Permission is hereby granted to freely copy and redistribute this
software, provided that the author is clearly credited in all
copies and derivations. This software is provided ``As Is'' and
without any express or implied warranties.
X
*/
X
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <errno.h>
#include "chat.h"
X
char chatter_rcsid[] = "$Id: chatter.c,v 1.2 90/10/26 19:55:20 darcy Exp Locker: darcy $\b ";
X
extern char chs_rcsid[];
X
#define MAX_CHATTERS 32
CHATTER u[MAX_CHATTERS];
X
char progname[64];
X
void cleanup(int sig) /* exit through here always */
{
X ch_close();
X fprintf(stderr, "\nchatter exiting\n");
X exit(sig);
}
X
/* open message queue */
void init(void)
{
X char *p;
X
X if ((p = ch_init()) != NULL)
X {
X fprintf(stderr, "%s: %s\n", progname, p);
X exit(1);
X }
}
X
void main(int argc, char **argv)
{
X int k, u_id;
X char ch, msgbuf[512], message[256];
X
X strcpy(progname, argv[0]);
X
X /* all trap everything to go through cleanup */
X signal(SIGINT, cleanup);
X signal(SIGABRT, cleanup);
X signal(SIGKILL, cleanup);
X signal(SIGTERM, cleanup);
X
X init();
X
X /* reset all channels */
X for (k = 0; k < MAX_CHATTERS; k++)
X u[k].channel = 0;
X
X for (;;) /* till the stars fall from the sky */
X {
X while ((u_id = ch_get(msgbuf)) == -1)
X ;
X
X if (u[u_id].channel == 0)
X u[u_id].channel = '0';
X
X ch = u[u_id].channel;
X
X switch (*msgbuf)
X {
X case 'o': /* open a chat channel */
X strcpy(u[u_id].logname, msgbuf + 1);
X sprintf(msgbuf, "[%-12.12s] Joining Chat", u[u_id].logname);
X
X /* advise the chat world of newcomer */
X for (k = 0; k < MAX_CHATTERS; k++)
X if (u[k].channel)
X ch_send(msgbuf, k);
X
X break;
X
X
X case 'x': /* user exiting from chat */
X sprintf(msgbuf, "[%-12.12s] Leaving Chat", u[u_id].logname);
X
X /* check each user */
X for (k = 0; k < MAX_CHATTERS; k++)
X {
X if (k == u_id) /* this user */
X u[k].channel = 0;
X else if (u[k].channel) /* other user */
X if (u[k].channel == ch) /* same channel */
X ch_send(msgbuf, k);
X }
X
X ch_send(NULL, u_id); /* remove user from list */
X break;
X
X case 'c': /* change channel */
X if (isascii(msgbuf[1])) /* only allow ASCII */
X {
X if (msgbuf[1] == '*')
X {
X int c = '0';
X
X while (isascii(c))
X {
X if (c == '*')
X continue;
X
X for (k = 0; k < MAX_CHATTERS; k++)
X if (u[k].channel == c)
X k = MAX_CHATTERS + 1;
X
X if (k == MAX_CHATTERS)
X {
X u[u_id].channel = c;
X sprintf(msgbuf,
X "[%-12.12s] switched to channel %c",
X u[u_id].logname, c);
X
X for (k = 0; k < MAX_CHATTERS; k++)
X if (u[k].channel)
X ch_send(msgbuf, k);
X
X break;
X }
X
X c++;
X }
X
X break;
X }
X
X u[u_id].channel = msgbuf[1];
X sprintf(msgbuf, "[%-12.12s] switched to channel %c",
X u[u_id].logname, u[u_id].channel);
X
X for (k = 0; k < MAX_CHATTERS; k++)
X if (u[k].channel)
X ch_send(msgbuf, k);
X }
X
X break;
X
X case 's': /* show users */
X for (k = 0; k < MAX_CHATTERS; k++)
X {
X if (u[k].channel)
X {
X sprintf(msgbuf, "[%-12.12s] is on channel %c",
X u[k].logname, u[k].channel);
X ch_send(msgbuf, u_id);
X }
X }
X
X break;
X
X case 'n': /* change user's display name */
X if (msgbuf[1])
X strcpy(u[u_id].logname, msgbuf + 1);
X break;
X
X case 'm': /* send a message */
X msgbuf[64] = 0;
X sprintf(message, "[%-12.12s] %s",
X u[u_id].logname, msgbuf + 1);
X
X for (k = 0; k < MAX_CHATTERS; k++)
X if (u[k].channel == ch)
X ch_send(message, k);
X
X break;
X
X case 'v': /* send a message */
X ch_send(chatter_rcsid + 1, u_id);
X ch_send(chs_rcsid + 1, u_id);
X break;
X }
X }
}
SHAR_EOF
chmod 0644 chatter.c ||
echo 'restore of chatter.c failed'
Wc_c="`wc -c < 'chatter.c'`"
test 4071 -eq "$Wc_c" ||
echo 'chatter.c: original size 4071, current size' "$Wc_c"
# ============= chc_msg.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'chc_msg.c' &&
/*
chc_msg
X
support routines for chat client - message IPC version
Written by D'Arcy J.M. Cain
West Hill, Ontario
darcy at druid.UUCP
All rights reserved
X
This module is linked with chat to implement a message based
version of chat.
X
Permission is hereby granted to freely copy and redistribute this
software, provided that the author is clearly credited in all
copies and derivations. This software is provided ``As Is'' and
without any express or implied warranties.
X
*/
X
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include "chat.h"
X
char chc_rcsid[] = "$Id: chc_msg.c,v 1.2 90/10/26 19:55:28 darcy Exp Locker: darcy $\b ";
X
#define KEY 0x63
X
extern int getpid(void);
X
static struct msgbuf sndbuf, rcvbuf;
static int q;
static long my_pid;
X
#ifdef HALFDELAY_BROKEN
static void checker(int sig)
{
X extern int chat_suspended;
X
X if (!chat_suspended)
X while (chk_q())
X ;
X
X sigset(SIGALRM, checker);
X alarm(2);
}
#endif
X
/* open message queue */
char *ch_init(void)
{
X if ((q = msgget(KEY, 0666)) == -1)
X return("Can't open chat queue");
X
#ifdef HALFDELAY_BROKEN
X checker(0); /* set up timer */
#endif
X my_pid = getpid();
X return(NULL);
}
X
int ch_close(void) /* exit through here always */
{
X /* nothing to do in message IPC version */
X return(0);
}
X
void chc_send(char *s) /* send message to chatter */
{
X sndbuf.mtype = 1L;
X strcpy(sndbuf.mtext, s);
X msgsnd(q, &sndbuf, 256, 0);
}
X
/* don't block */
int ch_get(char *s)
{
X if (msgrcv(q, &rcvbuf, 256, my_pid, IPC_NOWAIT) > 0)
X {
X strcpy(s, rcvbuf.mtext);
X return(1);
X }
X
X return(0);
}
X
SHAR_EOF
chmod 0644 chc_msg.c ||
echo 'restore of chc_msg.c failed'
Wc_c="`wc -c < 'chc_msg.c'`"
test 1586 -eq "$Wc_c" ||
echo 'chc_msg.c: original size 1586, current size' "$Wc_c"
# ============= chs_msg.c ==============
sed 's/^X//' << 'SHAR_EOF' > 'chs_msg.c' &&
/*
chs_msg
X
support routines for chatter - message IPC version
Written by D'Arcy J.M. Cain
West Hill, Ontario
darcy at druid.UUCP
All rights reserved
X
This module is linked with chatter to implement a message IPC based
version of chatter.
X
Permission is hereby granted to freely copy and redistribute this
software, provided that the author is clearly credited in all
copies and derivations. This software is provided ``As Is'' and
without any express or implied warranties.
X
*/
X
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include "chat.h"
X
char chs_rcsid[] = "$Id: chs_msg.c,v 1.2 90/10/26 19:55:31 darcy Exp Locker: darcy $\b ";
X
#define KEY 0x63
X
static struct msgbuf sndbuf, rcvbuf;
static struct msqid_ds msqid;
static int q;
X
static long u_pid[MAX_CHATTERS];
X
static int get_u(long i)
{
X int k;
X
X for (k = 0; k < MAX_CHATTERS; k++)
X if (u_pid[k] == i)
X return(k);
X
X return(-1);
}
X
/* open message queue */
char *ch_init(void)
{
X if ((q = msgget(KEY, 0666 | IPC_CREAT)) == -1)
X return("Chat queue in use");
X
X return(NULL);
}
X
int ch_close(void) /* exit through here always */
{
X /* remove chat message queue */
X return(msgctl(q, IPC_RMID, NULL));
}
X
void ch_send(char *s, int id) /* send message to user */
{
X if (s == NULL)
X u_pid[id] = 0;
X else if (u_pid[id])
X {
X sndbuf.mtype = u_pid[id];
X strcpy(sndbuf.mtext, s);
X msgsnd(q, &sndbuf, 256, 0);
X }
}
X
/* block until a message is received */
int ch_get(char *s)
{
X int u;
X
X /* check for dead process */
X for (u = 0; u < MAX_CHATTERS; u++)
X {
X if (u_pid[u])
X {
X if ((kill(u_pid[u], 0)) /* && (errno == ESRCH) */ )
X /* We shouldn't have to test */
X /* for ESRCH since that is */
X /* only theoretical return */
X {
X while (msgrcv(q, &rcvbuf, 256, u_pid[u], IPC_NOWAIT) != -1)
X ;
X
X /* simulate a close command */
X strcpy(s, "x");
X u_pid[u] = 0;
X return(u);
X }
X }
X }
X
X if (msgrcv(q, &rcvbuf, 256, 1L, 0) == -1)
X return(-1);
X
X /* set up various variables from message */
X strcpy(s, rcvbuf.mtext);
X msgctl(q, IPC_STAT, &msqid);
X
X if ((u = get_u(msqid.msg_lspid)) == -1)
X {
X if ((u = get_u(0L)) == -1)
X {
X strcpy(sndbuf.mtext, "e2 Chatter table full");
X sndbuf.mtype = msqid.msg_lspid;
X msgsnd(q, &sndbuf, 256, 0);
X return(-1);
X }
X else
X u_pid[u] = msqid.msg_lspid;
X }
X
X return(u);
}
X
SHAR_EOF
chmod 0644 chs_msg.c ||
echo 'restore of chs_msg.c failed'
Wc_c="`wc -c < 'chs_msg.c'`"
test 2340 -eq "$Wc_c" ||
echo 'chs_msg.c: original size 2340, current size' "$Wc_c"
# ============= chat.h ==============
sed 's/^X//' << 'SHAR_EOF' > 'chat.h' &&
/*
X
chat.h
Written by D'Arcy J.M. Cain
West Hill, Ontario
darcy at cain
All rights reserved
X
This is the header file for chat programs
X
If NO_SH_ESC is defined, shell escapes are disabled.
X
If NO_CHG_NAME is defined, users cannot change their display name from
the default which is the login name.
X
If NO_SHOW_USERS is defined, The /s command to show other users on the
system is disabled.
X
Some curses libraries in SV3.2 (and perhaps others) have a bug in that
halfdelay does not work as advertised. To get around this define the
constant HALFDELAY_BROKEN. This will cause code to be substituted which
uses a 2 second alarm to check the queue for incoming messages. If you
don't know if this is necessary on your system then compile without it
and see if you can receive messages from others without hitting a key.
If not then recompile with the constant defined.
X
*/
X
#define MAX_CHATTERS 32
X
typedef struct {
X short channel; /* for multiple chats on one system */
X char logname[32]; /* for display purposes */
} CHATTER;
X
void ch_send(char *s, int id);
void chc_send(char *s);
int ch_close(void);
char *ch_init(void);
int ch_get(char *s);
int chk_q(void);
SHAR_EOF
chmod 0444 chat.h ||
echo 'restore of chat.h failed'
Wc_c="`wc -c < 'chat.h'`"
test 1164 -eq "$Wc_c" ||
echo 'chat.h: original size 1164, current size' "$Wc_c"
# ============= lchat ==============
sed 's/^X//' << 'SHAR_EOF' > 'lchat' &&
:
# $Id: lchat,v 1.2 90/10/26 22:53:50 darcy Exp $
# This script calls chat with some arguments. Set LOGFILE equal to
# a log file to capture your session to. Set REALNAME to the name
# to display on the output.
X
# If a user's name is entered, chat is called via chatyell which
# sends a message to the named user to run chat before running chat.
X
LOGFILE=/usr/darcy/chat.log
REALNAME="D'Arcy"
X
echo "\n`date`" >> $LOGFILE
X
if [ $# = 0 ]
then
X chat -n $REALNAME -f $LOGFILE
else
X chatyell $1 -n $REALNAME -f $LOGFILE $2 $3 $4 $5
fi
X
SHAR_EOF
chmod 0544 lchat ||
echo 'restore of lchat failed'
Wc_c="`wc -c < 'lchat'`"
test 537 -eq "$Wc_c" ||
echo 'lchat: original size 537, current size' "$Wc_c"
# ============= chatyell ==============
sed 's/^X//' << 'SHAR_EOF' > 'chatyell' &&
:
# chatyell tells someone to join the chat.
# Written by D'Arcy J.M. Cain
# $Id: chatyell,v 1.2 90/10/26 22:53:46 darcy Exp $
X
if [ $# -lt 1 ]
then
X echo "Usage: chatyell user"
else
# The following test isn't perfect. If you want to chat
# with user bill and he is not logged in but billy is then
# the test shows bill as logged in. I'm sure there is a
# really easy way to find out if someone is logged in but
# I just don't happen to know it.
X if [ `who | awk "/$1/ {print \$1}" | wc -l` != 0 ]
X then
X write $1 <<- END_ECHO
X $LOGNAME wants to chat with you.
X Type chat at the prompt
X END_ECHO
X chat $2 $3 $4 $5 $6 $7 $8 $9
X else
X echo "$1 not currently logged on"
X fi
fi
SHAR_EOF
chmod 0555 chatyell ||
echo 'restore of chatyell failed'
Wc_c="`wc -c < 'chatyell'`"
test 682 -eq "$Wc_c" ||
echo 'chatyell: original size 682, current size' "$Wc_c"
# ============= chat.readme ==============
sed 's/^X//' << 'SHAR_EOF' > 'chat.readme' &&
chat
====
X
Written by D'Arcy J.M. Cain 1990
(darcy at cain)
All rights reserved
X
Permission is hereby granted to freely copy and redistribute this
software, provided that the author is clearly credited in all
copies and derivations. This software is provided ``As Is'' and
without any express or implied warranties.
X
Chat allows more than one user on a system to be involved
in a conference via their terminal. It consists of a foreground
part and a background part.
X
chatter is the background process. It looks for messages from
other processes and sends messages to them. It should be put into
inittab so that it always restarts.
X
chat is the front end and is the program run by users wishing to
join or start a chat. In chat, lines starting with / are commands.
enter /? or /h for a list of commands
X
To call chat simply enter chat from the command line. Various
options are available and are accessed by adding '-x' to the command
where x is one of the following letters:
X
h Displays a usage message instead of running the program.
n Takes the following name and uses it instead of login name.
f Takes the following file and keeps a log of the conversation in it.
X
Example:
X
chat -n "D'Arcy" -f chat.log
X
This starts chat, sets up the name as D'Arcy, opens the file chat.log
and keeps a record of the chat in it. Note that the quotes around
D'Arcy are only neccessary because of the apostrophe.
X
The n option can be set from within the program as well.
X
Move chat.make to Makefile and run make to create the programs.
X
X
Chat Wish List:
X
These are a few things that I hope to add to chat later. If you can
think of other enhancements please let me know.
X
- A TLI version. I have made a small start on this but if anyone wants
X to give it a try, go ahead. Use the ???_msg.c files as models. You
X should be able to write ???_tli.c files that just link into the other
X files without changing them.
X
- A monitor program. This is mostly a matter of deciding what it should
X do. One idea would be to print the name of the user any time there was
X any activity from the chatter. This could be monitored in any way one
X chooses. A simplistic method would be to run the monitor program in
X background and allow it to interupt the user each time there was any
X activity. Of course there are other possibilities. On my system, for
X example, I would put it in background and pipe it to a program that
X displays the name on the LED's on my front panel.
X
X
Enjoy.
D'Arcy J.M. Cain
(darcy at druid)
X
SHAR_EOF
chmod 0444 chat.readme ||
echo 'restore of chat.readme failed'
Wc_c="`wc -c < 'chat.readme'`"
test 2516 -eq "$Wc_c" ||
echo 'chat.readme: original size 2516, current size' "$Wc_c"
# ============= chat.make ==============
sed 's/^X//' << 'SHAR_EOF' > 'chat.make' &&
# Makefile for chat
# Written by D'Arcy J.M. Cain
# $Id: chat.make,v 1.2 90/10/26 22:53:40 darcy Exp $
#
X
# So far only message based method supported.
METHOD=msg
X
all: chat chatter
X
chatter: chatter.o chs_$(METHOD).o
X $(CC) $(CFLAGS) chatter.o chs_$(METHOD).o $(LDFLAGS) -o chatter
X
chat: chat.o chc_$(METHOD).o
X $(CC) $(CFLAGS) chat.o chc_$(METHOD).o $(LDFLAGS) -lcurses -o chat
X
chat.o: chat.c chat.h
X
chatter.o: chatter.c chat.h
X
chc_$(METHOD).o: chc_$(METHOD).c chat.h
X
chs_$(METHOD).o: chs_$(METHOD).c chat.h
SHAR_EOF
chmod 0444 chat.make ||
echo 'restore of chat.make failed'
Wc_c="`wc -c < 'chat.make'`"
test 520 -eq "$Wc_c" ||
echo 'chat.make: original size 520, current size' "$Wc_c"
exit 0
--
D'Arcy J.M. Cain (darcy at druid) |
D'Arcy Cain Consulting | I support gun control.
West Hill, Ontario, Canada | Let's start with the government!
+ 416 281 6094 |
More information about the Alt.sources
mailing list