memchat 16 user chat using shared memory
Dave Binette
dbin at norsat.UUCP
Fri Sep 22 17:19:48 AEST 1989
Several weeks ago I posted a request to USENET asking for
code fragments of programs that used interprocess communications.
The response was encouraging, thank you all for the help.
In return I am submitting this for your amusement/edification.
A small low overhead multiuser chat program for 16 users using
shared memory.
It uses an algorithm I've never seen anywhere else, but then...
I haven't been looking for chat algorithms. Its *definately*
not the best, but it works. Theoretically it can break and lose
a message but I've never seen it happen (yet).
------------------------ chop chop -----------------------------
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by dbin on Fri Sep 22 00:14:33 PDT 1989
# Contents: README makefile memchat.1 memchat.c
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
memchat 16 user shared memory chat program
Released to PUBLIC DOMAIN by David J. Binette
in appreciation of the replies to my request for IPC code fragments
on the USEers NETwork.
I wrote this code to utilize shared memory
A single executable called "memchat" is compiled.
There is no server.
The only tunable parameters in the code are:
#define MAXMSG 20 /* # of messages */
#define MSGSIZ 80 /* size of a typed line */
Again, I'd like to thank all those from USENET who responded to my requests
for code fragments and help regarding message Q's
-
uucp: {uunet,ubc-cs}!van-bc!norsat!dbin | 302-12886 78th Ave
bbs: (604)597-4361 24/12/PEP/3 | Surrey BC CANADA
voice: (604)597-6298 (Dave Binette) | V3W 8E7
@//E*O*F README//
chmod u=rw,g=r,o=r README
echo x - makefile
sed 's/^@//' > "makefile" <<'@//E*O*F makefile//'
# compilation for "memchat" under SCO XENIX 2.3.1
# sysname=XENIX
# nodename=norsat
# release=2.3.1
# version=SysV
# machine=i80386
# origin=3
#
# The source code for memchat.c, the executable memchat
# as well as the accompanying documentation README and memchat.1
# are placed in the public domain.
# Use it, sell it, do what you will.
# If your nice, you'll leave my name on it.
# If your kind, and you modify it, you'll put your name on it too!
# Author: uunet!norsat!dbin (David J. Binette)
memchat: memchat.c
cc -M3e -W3 -Od memchat.c -s -o memchat -lx
@//E*O*F makefile//
chmod u=rw,g=r,o=r makefile
echo x - memchat.1
sed 's/^@//' > "memchat.1" <<'@//E*O*F memchat.1//'
@.TH MEMCHAT 1 NORSAT
@.SH NAME
memchat \- 16 user Chat program using Shared Memory.
@.SH SYNOPSIS
@.B memchat
@.SH DESCRIPTION
This program sends and receives data via shared memory.
V1.0 Released to PUBLIC DOMAIN by David J. Binette in appreciation of the replies to a request for code fragments on USENET.
@.SH EXAMPLES
memchat
@.RE
@.SH SEE ALSO
write(C),
hello(C),
mail(C)
@.SH RETURN VALUE
Returns 0 for normal successfull exit.
@.br
Returns 255 if memchat was full.
@.br
Failed calls return with the errno of the failed function.
@.SH NOTES
No warranties expressed or implied, use at your own risk.
@.SH BUGS
The algorithm may break (theoretically) and lose a message.
@//E*O*F memchat.1//
chmod u=rw,g=r,o=r memchat.1
echo x - memchat.c
sed 's/^@//' > "memchat.c" <<'@//E*O*F memchat.c//'
/* memchat.c
*
* 16 user shared memory chat program
* Released to public domain by David J. Binette
* in appreciation of the replies to my request for
* IPC code fragments on the USEers NETwork.
*
* The algorithm used may break (theoretically) but I've never seen
* it happen, its just a matter of timing. At worst, a message is lost.
*
* The source code for memchat.c, the executable memchat
* as well as the accompanying documentation README and memchat.1
* are placed in the public domain.
* Use it, sell it, do what you will.
* If your nice, you'll leave my name on it.
* If your kind, and you modify it, you'll put your name on it too!
*/
/*
* Program Name : memchat
* Associated files: memchat.1 makefile memchat.c
* Author : uunet!norsat!dbin (David J. Binette)
* Version : 1.0
* Release Date : Thu Sep 21 21:38:47 PDT 1989
* Revision History:
* :
* :
* :
* :
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sd.h>
#include <signal.h>
#include <termio.h>
#include <sys/ioctl.h>
/* ------------------------------------------------------- */
/* you can change this if you want */
#define MAXMSG 20 /* # of messages */
#define MSGSIZ 80 /* size of a typed line */
/* ------------------------------------------------------- */
#define KEY (key_t) 60
#define FNULL (struct COMMON *) 0
#define FAILURE (struct COMMON *) -1
#define FALSE 0
#define TRUE 1
#define EOS '\0'
/* ------------------------------------------------------- */
extern int errno;
int clean();
int Rval=0;
int shmid;
unsigned int mynum;
char myname[L_cuserid+1];
struct COMMON * base;
char Inbuf[MSGSIZ+1]; /* this needn't be global */
/* ------------------------------------------------------- */
extern struct COMMON {
unsigned int usr;
unsigned int map[MAXMSG];
char txt[MAXMSG][L_cuserid + 2 + MSGSIZ+1];
};
/* ------------------------------------------------------- */
void putmsg(s)
char *s;
{
int i=MAXMSG;
while(i==MAXMSG)
for(i=0; i<MAXMSG; i++)
if(base->map[i] == 0)
{
base->map[i] = mynum;
strcpy(base->txt[i],myname);
strcat(base->txt[i],"> ");
strcat(base->txt[i],s);
base->map[i] = base->usr &~mynum;
break;
}
}
/* ------------------------------------------------------- */
int getmsg()
{
int i;
int r=0;
for(i=0; i<MAXMSG; i++)
if(base->map[i] & mynum)
{
r=1;
puts(base->txt[i]);
base->map[i] &= ~mynum;
}
return(r);
}
/* ------------------------------------------------------- */
int getaline()
{
int r;
*Inbuf=EOS;
if(r=(rdchk(fileno(stdin))>0))
if(fgets(Inbuf,MSGSIZ,stdin))
if(*Inbuf)
putmsg(Inbuf);
return(r);
}
/* ------------------------------------------------------- */
void main()
{
int i;
int created=0;
Rval=0;
if(!cuserid(myname))
strncpy(myname,"unknown",L_cuserid);
signal(SIGINT, clean);
if((shmid = shmget(KEY, sizeof(struct COMMON), 0)) < 0)
{
if((shmid = shmget(KEY, sizeof(struct COMMON), IPC_CREAT | 0666)) < 0)
{
Rval=errno;
perror("shmget failed");
exit(Rval);
}
created=1;
}
if((base = (struct COMMON *)shmat(shmid, FNULL, 0)) == FAILURE)
{
Rval=errno;
perror("shmat failed");
exit(Rval);
}
if(created) /* initialize the common area */
{
base->usr=0;
for(i=0; i<MAXMSG; i++)
{
base->map[i]=0;
base->txt[i][0]=EOS;
}
}
/* get a user # */
for(mynum=0x8000; mynum; mynum>>=1) /* portable? not likely */
{
if(!(base->usr & mynum))
break;
}
if(mynum)
{
putmsg("Arrives!");
base->usr|=mynum;
}
else
{
puts("Sorry, no more users allowed in chat.");
Rval=255;
clean();
}
puts("\nWelcome to memchat V1.0");
puts("Type in your text and press [ENTER]");
puts("Press [DEL] to end session\n");
for( ; ; )
if(!(getaline() | getmsg()))
nap(125L);
clean();
}
/* ------------------------------------------------------- */
clean()
{
int i;
putmsg("Departs!");
for(i=0; i<MAXMSG; i++)
base->map[i] &= ~mynum;
base->usr &= ~mynum;
shmdt(base);
shmctl(shmid, IPC_RMID, NULL);
exit(Rval);
}
/* ------------------------------------------------------- */
@//E*O*F memchat.c//
chmod u=rw,g=r,o=r memchat.c
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
24 119 742 README
19 98 562 makefile
33 112 672 memchat.1
215 529 4244 memchat.c
291 858 6220 total
!!!
wc README makefile memchat.1 memchat.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
---
"If I was smarter than I was bad, I wouldn't get in any trouble"
(Laura my 4 yr. old daughter)
uucp: {uunet,ubc-cs}!van-bc!norsat!dbin | 302-12886 78th Ave
bbs: (604)597-4361 24/12/PEP/3 | Surrey BC CANADA
voice: (604)597-6298 (Dave Binette) | V3W 8E7
More information about the Alt.sources
mailing list