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