Realtime talk for Systems V (IPC with message queues)
Lars Hammarstrand
lasse at daab.se
Wed Feb 1 21:02:51 AEST 1989
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# INSTALLATION
# MANIFEST
# Makefile
# defs.h
# disconnect.c
# doconnect.c
# main.c
# misc.c
# notify.c
# talk.1
# talk.c
# time.c
# window.c
# This archive created: Tue Dec 20 18:48:15 1988
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'INSTALLATION'" '(810 characters)'
if test -f 'INSTALLATION'
then
echo shar: "will not over-write existing file 'INSTALLATION'"
else
cat << \SHAR_EOF > 'INSTALLATION'
Tue Dec 20 15:37:30 MET 1988 (Lars Hammarstrand: ..!mcvax!enea!daab!lasse)
Installation procedure for the System V talk program;
-----------------------------------------------------
1) run "make talk"
2) Modify the BINDIR variable in Makefile so make knows where to put the
talk program for public use.
3) Add a dummy user named "talk" (with for example user ID 9999) in the
/etc/passwd file, and a dummy group (with for example group ID 9999)
in the /etc/group file.
Why? - Talk will be installed to run as a "set user ID" program with
this dummy user id, so it will be able to remove old message queues
and old tmp files. For security reasons: DO NOT USE ROOT OR OTHER
PRIVILEDGED USER ID'S.
4) run "make install"
5) If you want to format the manual into the file talk.doc:
run "make man"
SHAR_EOF
if test 810 -ne "`wc -c < 'INSTALLATION'`"
then
echo shar: "error transmitting 'INSTALLATION'" '(should have been 810 characters)'
fi
chmod 644 'INSTALLATION'
fi
echo shar: "extracting 'MANIFEST'" '(116 characters)'
if test -f 'MANIFEST'
then
echo shar: "will not over-write existing file 'MANIFEST'"
else
cat << \SHAR_EOF > 'MANIFEST'
INSTALLATION
MANIFEST
Makefile
defs.h
disconnect.c
doconnect.c
main.c
misc.c
notify.c
talk.1
talk.c
time.c
window.c
SHAR_EOF
if test 116 -ne "`wc -c < 'MANIFEST'`"
then
echo shar: "error transmitting 'MANIFEST'" '(should have been 116 characters)'
fi
chmod 644 'MANIFEST'
fi
echo shar: "extracting 'Makefile'" '(1013 characters)'
if test -f 'Makefile'
then
echo shar: "will not over-write existing file 'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
#
# Makefile for Sys V talk
# (with real time screen updates and message queues)
#
# Before "make install":
#
# Modify BINDIR so make knows where to put the talk program for
# public use.
#
# Add a dummy user named "talk" (user and group number 9999) to the
# /etc/passwd and /etc/group file. Talk will be installed to run as a
# "set user ID" program with this dummy user id, so it will be able to
# remove old message queues and old tmp files. For security reasons:
# DO NOT USE ROOT OR OTHER PRIVILEDGED USER ID'S.
#
USERID=talk # User id that should exist in /etc/passwd (uidnr: 9999)
GROUPID=talk # Group id that should exist in /etc/group (gidnr: 9999)
BINDIR=/usr/lbin
CFLAGS=-O
OBJS= doconnect.o disconnect.o notify.o main.o misc.o talk.o time.o window.o
talk: $(OBJS)
$(CC) $(LDFLAGS) -o talk $(OBJS) -lcurses
talk.doc: talk.1
nroff -man talk.1 > talk.doc
man: talk.doc
install: talk
cp talk $(BINDIR)
chown $(USERID) $(BINDIR)/talk
chgrp $(GROUPID) $(BINDIR)/talk
chmod 6111 $(BINDIR)/talk
SHAR_EOF
if test 1013 -ne "`wc -c < 'Makefile'`"
then
echo shar: "error transmitting 'Makefile'" '(should have been 1013 characters)'
fi
chmod 644 'Makefile'
fi
echo shar: "extracting 'defs.h'" '(3488 characters)'
if test -f 'defs.h'
then
echo shar: "will not over-write existing file 'defs.h'"
else
cat << \SHAR_EOF > 'defs.h'
/*
* <LH:881125:v2.0>
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/errno.h>
#include <ctype.h>
#include <curses.h>
#include <signal.h>
#include <pwd.h>
#include <utmp.h>
/* window sizes */
#define MY_WINLINES (LINES / 2)
#define HIS_WINLINES (LINES - MY_WINLINES - 1)
/* Message queue commands <LH:881125:v2.0> */
#define CONNECT 0xF0
#define DISCONNECT 0xF3
#define DELETE 0xFC
#define END_OF_FILE 0x04
#define REFRESH 0x0C
#define BELL 0x07
/* Exit codes <LH:881125:v2.0> */
#define I_DISCONNECTED 1
#define HE_DISCONNECTED 2
#define NO_ANSWER 3
#define NOT_LOGGED_IN 4
#define TTY_DISABLED 5
#define PROGRAM_ERROR 6
/* other defines <LH:881125:v2.0> */
#define TIME_SIZE 19 /* size of window clock */
#define TICK_INTERVAL 2 /* clock update interval */
#define MAXTRY 3 /* max tries to notify user */
#define TRY_TIME 20 /* time between tries */
/* message queue defines <LH:881125:v2.0> */
#define MSGSIZE (sizeof (MSG) - sizeof (long))
#define ANYMSG (0)
#define MSGMASK 0600
/* macros <LH:881125:v2.0> */
#define printable(x) (x == '\n' || x == '\t' || isprint(x))
#define file_exist(x) (access(x, 0) == 0)
#define eq(s1,s2) (strcmp(s1,s2) == 0)
/* variable and function declarations <LH:881125:v2.0> */
extern WINDOW *mywin, *hiswin, *dividewin; /* the three windows */
extern int connected; /* whether actually talking */
extern int time_changed; /* to update elapsed time */
extern int master; /* whether master or slave */
extern int msgid; /* message queue id */
extern long time();
extern int out_of_date();
extern void clock_tick();
extern void interrupt(); /* intr trap (disconnect) */
extern void disconnect();
extern void doconnect();
extern void talk();
extern void update_time();
extern void screen_init();
extern void master_queue();
extern void slave_queue();
extern void error();
extern void sendmsg();
extern void setutent();
extern void add_my_window();
extern void add_his_window();
extern void wheader();
extern void wprevch();
extern void update_time_line();
extern char *notify(); /* ring user */
extern char *fullname(); /* full name of login name */
extern char *ctime(); /* get current time str */
extern char *strchr();
extern char *strrchr();
extern char *getlogin();
extern struct utmp *getutent();
extern struct passwd *getpwnam();
extern int mypid; /* current PID */
extern int readpid; /* current keyboard PID */
extern int hispid; /* other sides PID */
extern int errno;
extern key_t key; /* common key for msgget() */
extern char tmp[BUFSIZ]; /* general purpose ! */
extern char tempfile[40]; /* common temp file */
extern char *myname, *hisname, *histty;
extern char *progname; /* current program name */
extern char delchar; /* current delete char */
/*
* Message queue buffer. <LH-881125>
*
* Messages are sent from your own keyboard-read process to your own displays
* process (se talk.c). Your display-process will first show it on your window
* and then send it over to the other side. Messages comming from the other
* side (i.e: msg.from_pid == hispid) will show up at "his" window.
*/
typedef struct _msg
{
long to_pid; /* want only messages to this PID */
int from_pid; /* PID who sent message */
int c; /* the actual character (or cmd) */
} MSG;
extern MSG *getmsg();
SHAR_EOF
if test 3488 -ne "`wc -c < 'defs.h'`"
then
echo shar: "error transmitting 'defs.h'" '(should have been 3488 characters)'
fi
chmod 644 'defs.h'
fi
echo shar: "extracting 'disconnect.c'" '(1595 characters)'
if test -f 'disconnect.c'
then
echo shar: "will not over-write existing file 'disconnect.c'"
else
cat << \SHAR_EOF > 'disconnect.c'
#include "defs.h"
/*
* Trap the keyboard interrupt signal to force a disconnect. <LH:881125:v2.0>
*/
void
interrupt () /* program interrupted by signal - disconnect */
{
disconnect (I_DISCONNECTED);
}
/*
* Tell other side to disconnect, kill the keyboard-read process, clean up
* windows and then exit. <LH:881125:v2.0>
*/
void
disconnect (how)
int how;
{
static beenhere = FALSE;
if (beenhere++)
return;
alarm (0);
signal (SIGALRM, SIG_IGN);
signal (SIGINT, SIG_IGN);
signal (SIGHUP, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
if (readpid) /* kill keyboard-read process */
{
kill (readpid, 9);
wait ((int *)0);
}
sendmsg (hispid, DISCONNECT);
switch (how)
{
case I_DISCONNECTED:
waddstr (mywin, "\n[You have disconnected]");
break;
case HE_DISCONNECTED:
waddstr (mywin, "\n[Your party has disconnected]");
beep ();
break;
case PROGRAM_ERROR:
waddstr (mywin, "\n[Program failure - disconnected]");
break;
case NO_ANSWER:
wheader (mywin, "[Your party would not respond]\n");
break;
case NOT_LOGGED_IN:
sprintf (tmp, "[Your party is not logged on %]\n",
histty);
wheader (tmp);
break;
case TTY_DISABLED:
wheader (mywin, "[Your party has disabled messages]\n");
break;
}
wnoutrefresh (mywin);
wnoutrefresh (hiswin);
wnoutrefresh (dividewin);
doupdate ();
endwin ();
msgctl (msgid, IPC_RMID, 0);
unlink (tempfile); /* should have been done before */
printf ("\n");
if (how == PROGRAM_ERROR)
exit (4);
if (!connected)
notify (DISCONNECT);
exit(0);
}
SHAR_EOF
if test 1595 -ne "`wc -c < 'disconnect.c'`"
then
echo shar: "error transmitting 'disconnect.c'" '(should have been 1595 characters)'
fi
chmod 644 'disconnect.c'
fi
echo shar: "extracting 'doconnect.c'" '(2046 characters)'
if test -f 'doconnect.c'
then
echo shar: "will not over-write existing file 'doconnect.c'"
else
cat << \SHAR_EOF > 'doconnect.c'
#include "defs.h"
/*
* Establish connection between users.
*
* <LH:881125:v2.0>
*/
void
doconnect ()
{
mypid = getpid();
sprintf (tempfile, "/tmp/ta_%s.%s", hisname, myname);
if (!file_exist (tempfile) || out_of_date (tempfile))
{
unlink (tempfile);
master_queue ();
}
else
slave_queue ();
connected = TRUE;
wheader (mywin, "[Connected]\n");
update_time_line ();
beep ();
}
/*
* Create message queue for connection to slave and try to connect.
*
* <LH:881125:v2.0>
*/
void
master_queue ()
{
int try;
char *histty;
MSG *msgp;
sprintf (tempfile, "/tmp/ta_%s.%s", myname, hisname);
if (creat (tempfile, 0) == -1)
error("can't create %s", tempfile);
if ((key = ftok (tempfile, '\0')) == (key_t)-1)
error (tempfile);
if ((msgid = msgget (key, 0)) >= 0 && msgctl (msgid, IPC_RMID,0) == -1)
error ("Can't remove old message queue id (%d)", msgid);
if ((msgid = msgget (key, MSGMASK | IPC_CREAT)) == -1)
error ("Can't create new message queue.");
histty = notify (CONNECT);
sprintf (tmp, "[Waiting for your party to respond on %s]\n", histty);
wheader (mywin, tmp);
wnoutrefresh (mywin);
doupdate ();
for (try=1; try < MAXTRY; ++try)
{
sendmsg ((int)key, CONNECT);
alarm (TRY_TIME);
while (msgp = getmsg (mypid))
{
if (msgp->c == CONNECT)
{
hispid = msgp->from_pid;
return;
}
}
histty = notify (CONNECT);
sprintf (tmp, "[Ringing your party again on %s (retry %d)]\n",
histty, try);
wheader (mywin, tmp);
}
disconnect (NO_ANSWER);
/*NOTREACHED*/
}
/*
* Get message queue id for the slave connection.
*
* <LH:881125:v2.0>
*/
void
slave_queue ()
{
MSG *msgp;
sprintf (tempfile, "/tmp/ta_%s.%s", hisname, myname);
if ((key = ftok (tempfile, '\0')) == (key_t)-1)
error (tempfile);
unlink (tempfile);
if ((msgid = msgget (key, 0)) == -1)
error ("msgget: can't get msgid.");
alarm (5);
if ((msgp = getmsg (ANYMSG)) == NULL)
error ("Can't connect to master");
hispid = msgp->from_pid;
sendmsg (hispid, CONNECT);
}
SHAR_EOF
if test 2046 -ne "`wc -c < 'doconnect.c'`"
then
echo shar: "error transmitting 'doconnect.c'" '(should have been 2046 characters)'
fi
chmod 644 'doconnect.c'
fi
echo shar: "extracting 'main.c'" '(3121 characters)'
if test -f 'main.c'
then
echo shar: "will not over-write existing file 'main.c'"
else
cat << \SHAR_EOF > 'main.c'
#ifndef lint
static char sccsid[] = "@(#)talk.c 2.0 [Lars Hammarstrand] 88-11-23";
static char orgid[] = "@(#)talk.c 1.2 [Nigel Holder (C) - Baddow] 04/12/85";
#endif
/****************************************************************************
*
* VERS 2.0 Author: Lars Hammarstrand. (rewritten from 1.2)
* VERS 1.2 Orginal Author: Nigel Holder (ver 1.2 04/12/85)
*
*
* VERS 2.0 HISTORY: (Lars Hammarstrand)
*
* 1) fixed erasechar to work.
* 2) added a message queue as a communikation channel instead
* of named pipes. (much faster)
* 3) added realtime updates of screen.
* 4) added a realtime keyboard-read process.
* 5) replaced and cleaned up exit functions.
* 6) cleaned up clock funcktions so it will show true elapsed time.
*
*
* VERS 1.2 HISTORY: (Nigel Holder)
*
* Date : 12 June 1985
* 4 December 1985 changed elapsed time stuff
* to be synchronous to windows
*
* Copyright (C) 1986 by Nigel Holder
*
* Permission to use this program is granted, provided it is not
* sold, or distributed for direct commercial advantage, and includes
* the copyright notice and this clause.
*
*
* Talk - an interactive communication program that allows users
* to talk on a character basis (as opposed to a line basis, as for
* the system write utility).
*
* Written for System V as it uses named pipes !
* (and BSD already has a talk utility).
*
* Old 1.2 bugs:
*
* 1. Not as good as BSD talk, but it suffices.
* (restricted to current host machine)
*
* 2. Really need select() type statement (BSD) instead of sleeping
* for 1 second between no input or output activity.
* (version 8 should fix this).
*
* 3. Should check for name fields in dividewin overflowing screenwidth
*
* 4. Probably should disable CTRL-c stopping program when connected.
*
****************************************************************************/
#include "defs.h"
int connected = FALSE; /* whether actually talking */
int time_changed = FALSE; /* to update elapsed time */
WINDOW *mywin, *hiswin, *dividewin; /* the three windows */
int hispid, mypid, readpid, msgid;
char tmp[BUFSIZ]; /* general purpose ! */
char tempfile [40];
char *myname = NULL;
char *hisname = NULL;
char *histty = NULL;
char *progname;
char delchar;
key_t key;
main (argc, argv)
int argc;
char *argv[];
{
if (progname = strrchr (argv[0], '/'))
++progname;
else
progname = argv[0];
if (argc < 2)
{
fprintf (stderr, "usage: %s user [tty]\n", progname);
exit (1);
}
hisname = argv[1];
if (argc > 2)
histty = argv[2];
if ((myname = getlogin()) == NULL)
{
fprintf (stderr, "You don't exist. Go away.\n");
exit (2);
}
signal (SIGINT, SIG_IGN); /* play safe */
signal (SIGHUP, SIG_IGN);
signal (SIGQUIT, SIG_IGN);
screen_init (); /* set up windows */
signal (SIGINT, interrupt); /* gracefully trap signals */
signal (SIGHUP, interrupt);
signal (SIGQUIT, interrupt);
signal (SIGALRM, clock_tick); /* increment clock counter */
doconnect (); /* tell'm I want'o talk with'm */
talk (); /* let your fingers do the walking */
/*NOTREACHED*/
}
SHAR_EOF
if test 3121 -ne "`wc -c < 'main.c'`"
then
echo shar: "error transmitting 'main.c'" '(should have been 3121 characters)'
fi
chmod 644 'main.c'
fi
echo shar: "extracting 'misc.c'" '(1974 characters)'
if test -f 'misc.c'
then
echo shar: "will not over-write existing file 'misc.c'"
else
cat << \SHAR_EOF > 'misc.c'
#include "defs.h"
/*
* Print error message and disconnect.
*/
void
error (message, arg1, arg2)
char *message, *arg1, *arg2;
{
static char beenhere = FALSE;
if (beenhere++)
return;
wmove (hiswin, HIS_WINLINES - 2, 0);
wprintw (hiswin, "%s: ", progname);
wprintw (hiswin, message, arg1, arg2);
wrefresh (hiswin);
disconnect (PROGRAM_ERROR);
}
/*
* Read from message queue, any message dedicated to this process.
*
* The returned message does also include information about which
* process it was sent from.
*
* <LH:881125:v2.0>
*/
MSG *
getmsg (pid)
int pid;
{
static MSG msg;
register MSG *msgp = &msg;
if (msgrcv (msgid, msgp, MSGSIZE, (long)pid, 0) == -1)
{
switch (errno)
{
case EINTR: /* interrupted */
return (NULL);
case EIDRM: /* msgid removed */
disconnect (HE_DISCONNECTED);
return (NULL);
default: /* other problems */
error ("msgrcv");
return (NULL);
}
}
return (msgp);
}
/*
* Send a character or command to a specific process.
*
* <LH:881125:v2.0>
*/
void
sendmsg (pid, c)
int pid;
int c;
{
static MSG msg;
register MSG *msgp = &msg;
msgp->to_pid = pid;
msgp->from_pid = mypid;
msgp->c = c;
while (msgsnd (msgid, msgp, MSGSIZE, 0) == -1)
{
switch (errno)
{
case EINTR: /* interrupted */
continue;
case EIDRM: /* msgid removed */
default:
disconnect (HE_DISCONNECTED);
return;
}
}
}
/*
* Determine whether file is not in use.
*/
out_of_date(fname)
char *fname;
{
struct stat stat_buf;
if (stat (fname, &stat_buf) == -1) /* assume doesn't exist */
return (FALSE);
if ((time ((long *) 0) - stat_buf.st_mtime) > (MAXTRY * TRY_TIME))
return (TRUE);
return (FALSE);
}
/*
* Get full name of user from the gecos field of the passwd file.
*
* <LH:881125:v2.0>
*/
char *
fullname (logname)
char *logname;
{
register struct passwd *p;
return ((p = getpwnam (logname)) ? p->pw_gecos : "no user");
}
SHAR_EOF
if test 1974 -ne "`wc -c < 'misc.c'`"
then
echo shar: "error transmitting 'misc.c'" '(should have been 1974 characters)'
fi
chmod 644 'misc.c'
fi
echo shar: "extracting 'notify.c'" '(888 characters)'
if test -f 'notify.c'
then
echo shar: "will not over-write existing file 'notify.c'"
else
cat << \SHAR_EOF > 'notify.c'
#include "defs.h"
/*
* Notify user you wish to talk to.
*
* <LH:881125:v2.0>
*/
char *
notify (how)
int how;
{
register struct utmp *user;
FILE *fp;
setutent ();
while ((user = getutent ()) != NULL) /* search for user */
{
if (!eq (user->ut_user, hisname))
continue;
if (!histty || eq (histty, user->ut_line))
break;
}
if (!user)
disconnect (NOT_LOGGED_IN);
sprintf (tmp, "/dev/%s", user->ut_line);
if ((fp = fopen (tmp, "w")) == NULL)
disconnect (TTY_DISABLED);
switch (how)
{
long curtime, time();
case CONNECT:
fprintf (fp, "\r\7%s (%s) is phoning - respond with 'talk %s' \n",
myname, fullname (myname), myname);
break;
case DISCONNECT:
time (&curtime);
fprintf (fp, "\r\7%s (%s) has stopped phoning [%s]\n",
myname, fullname (myname), ctime (&curtime));
break;
}
fclose (fp);
return (user->ut_line);
}
SHAR_EOF
if test 888 -ne "`wc -c < 'notify.c'`"
then
echo shar: "error transmitting 'notify.c'" '(should have been 888 characters)'
fi
chmod 644 'notify.c'
fi
echo shar: "extracting 'talk.1'" '(2210 characters)'
if test -f 'talk.1'
then
echo shar: "will not over-write existing file 'talk.1'"
else
cat << \SHAR_EOF > 'talk.1'
.TH Talk 1
.SH NAME
talk \- talk to another user
.SH SYNOPSIS
.B talk user [ tty ]
.SH DESCRIPTION
.PP
Talk is a utility that enables two users to interactively
communicate on a character basis on split screens.
It is intended to supersede the write utility for interactive
use by providing a more useful service.
Talk is invoked with a user name and an optional tty name thus :-
talk user [ tty8 ]
.PP
If user happens to be logged in more than once and no tty name is
supplied, talk will use the first entry in /etc/utmp (as used by who).
.PP
Talk will then attempt to notify the requested user that you are
trying to talk with him.
Trying to talk to a user may fail for two reasons :-
The requested user is not logged in.
The requested user has disabled messages (via mesg)
.PP
If the user doesn't answer, talk will keep notifying him.
After a reasonable number of retries, talk will give up and exit.
.PP
To reply to a user trying to talk to you, you should type
talk user (as shown in the request message).
.PP
When your party has connected you may both begin to talk (this
will be indicated by the bell ringing on your terminal).
The name of the person you are talking to and an elapsed time
indicator will appear in the centre of the screen.
You will notice that there are bursts of input and
output - this is due to the way they are handled within talk.
In order to avoid busy waiting, a sleep of one
second occurs whenever there is no activity.
.bp
.PP
Certain characters when typed have special meaning :-
ctrl-l - Refresh the screen. Useful if the
screen gets corrupted.
ctrl-d - Disconnect - finish talking.
ctrl-g - Ring the bell on other users terminal.
delete - Delete the character before the cursor
(works backwards over lines as well).
Uses your normal delete key.
ctrl-c - Forced exit. This has the same effect
as disconnect, although it may be
used at any stage of the proceedings
(ie. before connection has occured).
.SH FILES
/etc/utmp to find recipient's tty
/tmp/ta_xxxxxxxx tmp file to get a uniq msgkey.
SHAR_EOF
if test 2210 -ne "`wc -c < 'talk.1'`"
then
echo shar: "error transmitting 'talk.1'" '(should have been 2210 characters)'
fi
chmod 644 'talk.1'
fi
echo shar: "extracting 'talk.c'" '(1317 characters)'
if test -f 'talk.c'
then
echo shar: "will not over-write existing file 'talk.c'"
else
cat << \SHAR_EOF > 'talk.c'
#include "defs.h"
/*
* Talk() forks of a demon whose only task is to serve my own talk process
* (through the message queue) with characters read from the keyboard. Talk()
* interprets messages comming from my own PID as characters (or commands)
* to be displayed on my own window. If the character is accepteble it is
* then sent over to the corresponding talk process.
*
* <LH:881125:v2.0>
*/
void talk() /* talk to other user */
{
char c;
register MSG *msgp;
wmove (hiswin, 0, 0); /* start cursor positions */
wmove (mywin, 1, 0);
delchar = erasechar(); /* get current erase char */
if ((readpid = fork()) == 0) /* fork of keyboard-read process */
{
setpgrp();
while (1)
{
read (0, &c, 1);
/* send char to my self */
sendmsg (mypid, (c == delchar) ? DELETE : c);
}
}
else if (readpid == -1)
error ("cannot fork");
alarm (TICK_INTERVAL); /* trigg time counter */
while (1)
{
wnoutrefresh (mywin); /* place cursor in my own window */
doupdate(); /* update screen */
if (msgp = getmsg (mypid)) /* returns NULL if interrupted */
{
if (msgp->from_pid == mypid)
add_my_window (msgp->c);
else if (msgp->from_pid == hispid)
add_his_window (msgp->c);
}
if (time_changed)
update_time(); /* display elapsed time */
}
}
SHAR_EOF
if test 1317 -ne "`wc -c < 'talk.c'`"
then
echo shar: "error transmitting 'talk.c'" '(should have been 1317 characters)'
fi
chmod 644 'talk.c'
fi
echo shar: "extracting 'time.c'" '(1240 characters)'
if test -f 'time.c'
then
echo shar: "will not over-write existing file 'time.c'"
else
cat << \SHAR_EOF > 'time.c'
#include "defs.h"
static int elapsed_time = 0;
static char elapsed[] = "[%02d:%02d:%02d] ";
static int x = 0;
static int y = 0;
/*
* Update the elapsed_time counter and set the global flag to indicate time
* should be updated
*
* <LH:881125:v2.0>
*/
void
clock_tick()
{
signal (SIGALRM, clock_tick);
elapsed_time += TICK_INTERVAL;
time_changed = TRUE;
alarm (TICK_INTERVAL);
}
/*
* Update current elapsed time on the status line.
* (will show up on next doupdate())
*
* <LH:881125:v2.0>
*/
void
update_time()
{
register tm = elapsed_time;
register WINDOW *win = dividewin;
wmove (win, y, x);
wstandout (win);
wprintw (win, elapsed, tm/3600, tm/60, tm%60);
wstandend (win);
wnoutrefresh (win);
time_changed = FALSE;
}
void update_time_line ()
{
register WINDOW *win = dividewin;
char time_temp [sizeof(elapsed)];
sprintf (time_temp, elapsed, 0, 0, 0);
sprintf (tmp, " %s is talking to %s (%s) ", myname, hisname,
fullname(hisname));
wmove (win, 0, (COLS - strlen(tmp) - strlen(time_temp)) / 2);
wstandout (win);
waddstr (win, tmp);
getyx (win, y, x); /* remember where to put time next round */
waddstr (win, time_temp);
wstandend (win);
wnoutrefresh (win);
}
SHAR_EOF
if test 1240 -ne "`wc -c < 'time.c'`"
then
echo shar: "error transmitting 'time.c'" '(should have been 1240 characters)'
fi
chmod 644 'time.c'
fi
echo shar: "extracting 'window.c'" '(2252 characters)'
if test -f 'window.c'
then
echo shar: "will not over-write existing file 'window.c'"
else
cat << \SHAR_EOF > 'window.c'
#include "defs.h"
/*
* Check for and act on any output to be displayed.
*
* <LH:881125:v2.0>
*/
void
add_his_window (c)
register c;
{
register WINDOW *win = hiswin;
switch (c)
{
case DISCONNECT:
disconnect (HE_DISCONNECTED);
/*NOTREACED*/
case DELETE :
wprevch (win);
wdelch (win);
break;
case BELL :
beep();
break;
default :
if (printable (c))
waddch (win, c);
break;
}
wnoutrefresh (win);
}
/*
* Check for and act on user input
*
* <LH:881125:v2.0>
*/
void
add_my_window(c)
register c;
{
register WINDOW *win = mywin;
switch (c)
{
case END_OF_FILE:
disconnect (I_DISCONNECTED);
/*NOTREACED*/
case REFRESH:
clearok (curscr, TRUE);
break;
case BELL:
beep();
break;
case DELETE:
wprevch (win);
wdelch (win);
break;
default :
if (printable (c))
waddch (win, c);
else
{
beep();
return;
}
break;
}
wnoutrefresh (win);
sendmsg (hispid, c); /* send character to other side */
}
/*
* Print message at head of window
*/
void
wheader (win, message)
register WINDOW *win;
char *message;
{
wmove (win, 0, 0);
wclrtoeol (win);
waddstr (win, message);
}
/*
* Initialise talk windows
*/
void
screen_init()
{
int i;
initscr();
mywin = newwin (MY_WINLINES, COLS, 0, 0);
hiswin = newwin (HIS_WINLINES, COLS, MY_WINLINES + 1, 0);
dividewin = newwin (1, COLS, MY_WINLINES, 0);
noecho ();
cbreak ();
scrollok (mywin, TRUE);
scrollok (hiswin, TRUE);
idlok (mywin, TRUE);
idlok (hiswin, TRUE);
wmove (dividewin, 0, 0);
for (i = 0 ; i < COLS ; i++)
waddch (dividewin, '-');
/* faster screen update (a la curses manual) */
wnoutrefresh (mywin);
wnoutrefresh (hiswin);
wnoutrefresh (dividewin);
}
/*
* Move cursor back to previous non-space char within window
*/
void
wprevch (win)
register WINDOW *win;
{
register x, y;
getyx (win, y, x);
if (--x < 0) {
if (--y < 0) {
wmove (win, 0, 0);
return;
}
for (x = win->_maxx - 1 ; x >= 0 ; --x)
{
wmove(win, y, x);
if (winch(win) != ' ')
return;
}
return;
}
wmove (win, y, x);
}
SHAR_EOF
if test 2252 -ne "`wc -c < 'window.c'`"
then
echo shar: "error transmitting 'window.c'" '(should have been 2252 characters)'
fi
chmod 644 'window.c'
fi
exit 0
# End of shell archive
More information about the Alt.sources
mailing list