[net.sources] Chat - A multi-user communication system.

slb@bnl.UUCP (San Barr hanging out @ The Beach) (02/13/85)

	Here's a pet project I've been working on for the last
few months.  

Enjoy!

(And don't forget to remove the signature!)

*--------------------------------CUT HERE-----------------------------------*
#!/bin/sh
#
# This is a shell archive.  Remove anything before this line and run the rest
# of this file through the 'sh' command.  Or use the 'unshar' command.
# ***************************************************************************
# 
# 	This is a copy of the Chat system developed at Brookhaven
# National Labs. to allow a group conversation between users.  Files
# included are:
# 
# 	chat.c		C-source for the Chat system.
# 
# 	chat.h		Easy access list of major Chat variables.
# 
# 	chat.1		Manual page for chat system.
# 
# 	cwho.c		C-source for the cwho command (similar to who(1))
# 
# 	ruser.c		C-source for the remove user system utility.
# 
# 
# Sanford L. Barr
# 39 Royalston Lane
# S. Setauket, N.Y. 11720
# slb@bnl.ARPA
# ..!decvax!philabs!sbcs!bnl!slb
# (516) 736-4155 (home)
# 
# ***************************************************************************
#
echo 'Start of Chat, part 01 of 01:'
echo 'x - Makefile'
sed 's/^X//' > Makefile << '/'
X#	Makefile for Chat system
X
X
XCFLAGS= -O
X
Xall: chat ruser cwho
X
Xchat: chat.c
X	cc chat.c $(CFLAGS) -o chat
X
Xcwho: cwho.c
X	cc cwho.c $(CFLAGS) -o cwho
X
Xruser: ruser.c
X	cc ruser.c $(CFLAGS) -o ruser
/
echo 'x - README'
sed 's/^X//' > README << '/'
XFiles included in this directory are as follow:
X
X	chat.c
X
X	This file is the source code for the chat system.  After
Xthis file has been compiled it must be setuid to "root" or another
Xsystem user with read-write permission on the directory in which
Xthe LOGFILE is stored.  (See chat.h)
X
X	chat.h
X
X	This file contains all the major Chat system variables. Included
Xare:
XMAXUSERS	= Maximum amount of users in a single chat session.
XLOGFILE		= User file for chat.  Similar to /etc/utmp in nature.
XPREFIX		= The prefix and directory name for system buffers.
XFNAME		= File containg list of users logged in host system (utmp)
XPAGER		= The utility to notify other system users.
XSYSTEMFILE	= ** File which holds "squelch" information. And info. on
X		  system status. (See README2).
X
X	cwho.c
X
X	Source for a small utility which prints a list of users logged
Xinto the Chat system  This file requires no special permission.
X
X	ruser.c
X
X	Due to some system malfunctions and/or screwups, on rare
Xoccasions a user may not be removed from the LOGFILE.  The drawback
Xis that messages still get sent to the user's buffer and could
Xaccount for a lenghty /tmp file.   If such an occurance ever happens
Xthis utility will allow you to delete the user from the LOGFILE without
Xdisturbing any other system users in chat.  This occurance has only 
Xhappened once during he duration of Chat's development.  But I included
Xthe utility just in case.
/
echo 'x - README2'
sed 's/^X//' > README2 << '/'
X
X	In the rare event that it is necessary to take the Chat system
Xdown it may be accomplished by simply using a standard editor on the
XChat SYSTEMFILE and adding  the line:
X
Xsystem-down
X
X	When called up Chat will display a system down notice
Xand exit.   This is a hangover from the development stage and I have
Xfound no practical use otherwise - enjoy it anoyhow.
X
X	In the rare event of a system user abusing the Chat system
Xor the users on it,  he/she may be denied access until the owner
Xfeels confident that the user has straightened out.  This is a last
Xresort.  The perferred methind would be to communicate wih the
Xuser in question first.  If that dosen't seem to work then you
Xmay remove their access.
X	To remove a user's access simply add a line to the
Xchat SYSTEMFILE saying
X
Xsquelch username
X
XWhere username is the user in question.  When the user tries
Xto enter Chat they will be given a notice regarding removal of
Xaccess.
/
echo 'x - chat.1'
sed 's/^X//' > chat.1 << '/'
X.TH CHAT 1 
X.SH NAME
Xchat \-  Chat with up to 10 users
X.SH SYNOPSIS
X.B chat
X.SH DESCRIPTION
X.I Chat,
Xis a multi-user communications system, Developed at Brookhaven National
Xlabs, which allows a group of users to join in conversation.
XThe maximum amount of users in a single
X.I Chat
Xsession is 10 by default.
X.PP
XUpon entering
X.I Chat
Xthe users logged into the current
XChat session are displayed, along with their tty, and when they
Xentered.  No prompt will be given but the various system
Xfunctions can be accessed at the touch of a key.
X.PP
XChat system functions are as follow
X.TP
Xno input
X.PP
XWithout input from the user's terminal
X.I Chat 
Xwill display all incoming
Xmessages from other users along with notification of when users enter
Xand exit the current chat session.  All messages from other users are
Xinclosed in "<" and ">" and include the sender's name, handle, and tty.  A
Xstandard message would look somthing like this:
X
X<05 joeluser(Handle)= This is a test message>
X
XUser login and logout notification is inclosed in asterisks (*) and describes
Xthe current status.  A sample message would looks something like this:
X
X** joeluser logged in(out) on 01 **
X
XA user may give themselves a handle by adding the enviorment variable
XHANDLE and defining it to their prefrence (up to 10 characters).
X.TP
Xl
XList users logged into host system.
X.PP
XThis command prints a list of users logged into the host system,
Xincluding their tty and when they logged in. (Similar to who(1))
X.TP
Xp
XPage a user to come into Chat.
X.PP
XThis command allows a user to page another user who's logged into the
Xhost system.  Upon typing this command a list of all users users is
Xdisplayed along with a Job number.  The user will then be prompted to
Xenter a Job to be paged.  The page will be sent through mail(1) so
Xas to not disturb the person being paged.
X.TP
Xs
XSend a message to all users in Chat.
X.PP
XAfter typing "s" the user will be prompted with "TEXT>" at which point
Xthe user is to enter his/her message to be sent out.  A
Xmessage may be up to 4 lines of 80 characters each and is terminated
Xby a carriage return.
X.TP
Xw
XDisplay all users logged into Chat.
X.PP
XThis command displays the name, handle, time and tty of all users
Xin chat.
X.TP
Xq
XExit chat session.
X.PP
XUpon receiving an INTERRUPT or QUIT signal, as well as the user typing "q",
XChat will exit the current session.
X.TP
X!
XShell escape.
X.PP
XThe shell escape allows a user to execute a command via sh(1).  Time consuming
Xcommands are not advised due to the fact Chat buffers all incoming
Xmessages which would swamp the user's terminal as soon as the
Xcommand returns control to
X.I Chat.
X.TP
X?
XPrint a command summary.
X.PP
XThis command will print a brief summary of all current
X.I Chat
Xcommands.
X.PP
XAll signals recieved by
X.I Chat, with the exception of SIGALRM and
XSIGKILL, will cause
X.I Chat
Xto exit and remove the user from the current logs.
X.SH FILES
X/etc/utmp	user's in host system
X.br
X/tmp/ct.*	message buffers
X.br
X/lib/chat_log	log of user's in current chat session
X.SH "SEE ALSO"
Xmail(1)
X.SH BUGS
XNone known of.
/
echo 'x - chat.c'
sed 's/^X//' > chat.c << '/'
X/*	Written by Sanford L. Barr @ Brookhaven Nat. Labs.  11/01/84	*/
X/*			     Chat ver 4.86				*/
X#define VERSION "4.86 by SLB"
X/*      Special credit to jpm@bnl.arpa for all his time and trouble	*/
X
X/****************************
X**	    CHAT           **
X**			   **
X**      A multi-user       **
X**  communication system   **
X****************************/
X
X#include <stdio.h>			/* All those .h files! */
X#include "chat.h"
X#include <signal.h>
X#include <sgtty.h>
X#include <sys/ioctl.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <utmp.h>
X#include <time.h>
X
Xstruct	logstruct {
X	char	tty[6];			/* User's tty */
X	char	uname[21];		/* User's name and handle */
X	char	intime[8];		/* Entered chat */
X}
Xnames[MAXUSERS];
X
Xstruct  tm      *localtime();
Xstruct	stat	sbuf;
Xstruct	logs	lbuf;
Xstruct	sgttyb	Nmode, Omode;
X
Xchar 	*mytty = "\0xxxxxxxxxxxxxxx",	/* User's tty */
X	login[8],			/* Time entered chat */
X	*myname = "\0xxxxxxxxx",	/* Username */
X	mixname[32],			/* Both uname and handle */
X	myfile[64],			/* User message file */
X	*handle = "(\0xxxxxxxx",
X	buffer[512],
X	*getenv(),
X	*rindex();
X
Xint	quit(),
X	users = 0,			/* No of users in Chat    */
X	lfile,				/* Descriptor for LOGFILE */
X	dummy;				/* The guy who wrote this */
X
XFILE	*fopen(),*popen(),*wfd;
X
Xint cptty(a, b)		/* Compare routine for qsort */
Xstruct logstruct  *a, *b;
X{
X	return(strcmp(a->tty, b->tty));
X}
X
Xmain()
X{
X	char 	inp,
X		*getlogin(),
X		*ttyname(),
X		jline[128],
X		*junk;			/* Used for handle and read */
X
X	int	i = 0,
X		s = 0,
X		l;
X
X	long	ti;
X
X	time(&ti);
X	prtime(localtime(&ti),login);			/* Set login time */
X
X	mytty = ttyname(2);				/* Get tty */
X	mytty = rindex(mytty,'/') + 1;
X	myname = getlogin();				/* Get username */
X	junk = &jline[0];
X
X	if ((wfd=fopen(SYSTEMFILE,"r")) != NULL) {	/* Squelch users */
X		for(;;) {
X			if (fgets(junk, 32, wfd) == NULL)
X				i = 1;
X			if (!strncmp(junk, "system-down", 11)) {
X				puts("The chat system is down at the moment.  It should be up shortly.");
X				exit(0);
X			}
X			if (!strncmp(junk, "squelch ", 8)) {
X				junk = junk + 8;
X				if (!strncmp(myname, junk, strlen(myname))) {
X				puts("\
XYou have been disallowed system access.\n\
XIf you have any questions, talk to your system administrator.");
X				exit(1);
X				}
X			}
X			if (i)
X				break;
X		}
X		if (fclose(wfd) == EOF) {
X			perror(SYSTEMFILE);
X			exit(1);
X		}
X	}
X	junk = &jline[0];
X	strcpy(mixname, myname);		/* Get handle and */
X	if ((junk=getenv("HANDLE")) != NULL) {	/* Add it to mixname */
X		strncat(handle, junk, 10);
X		strcat(handle,")");
X		strncat(mixname, handle, strlen(handle));
X	}
X
X	while (s < 19)				/* Catch all signals and */
X		if ((s++) != SIGALRM)		/* send them to quit()   */
X			signal(s, quit);
X
X
X	if (fclose(fopen(LOGFILE, "a")) == EOF) { /* Create logfile */
X		perror(LOGFILE);
X		exit(1);
X	} else
X		chmod(LOGFILE, 0644);
X
X	if ((lfile=open(LOGFILE, 0)) == EOF) {	/* Open the logfile for */
X		perror(LOGFILE);		/* Future use */
X		exit(1);
X	}
X
X	if (ridname() == EOF)			/* Clear out dead users */
X		exit(1);			/*        if any	*/
X
X	who(1);					/* Get who's logged in. */
X	if (users > MAXUSERS) {
X		puts("Sorry, no available slots left at the moment.  Try later");
X		exit(1);
X	}
X
X	sprintf(names[users].tty, "%5.5s", mytty);
X	sprintf(names[users].uname, "%-20.20s", mixname);
X	sprintf(names[users].intime, "%7.7s", login);
X
X	qsort(names, users+1, sizeof(*names), cptty);	/* Sort tty's */
X
X	if ((wfd=fopen(LOGFILE,"w")) == NULL) {
X		error("Couldn't open LOGFILE",1);
X		exit(1);
X	}
X
X					/* Add name, tty, time to log */
X	for (l = 0; l < users+1; l++)
X	fprintf(wfd, "%-5.5s%-20.20s%-7.7s", names[l].tty, names[l].uname,
X							names[l].intime);
X
X	if (fclose(wfd) == EOF) {
X		perror(LOGFILE);
X		quit();
X	}
X
X	strcpy(myfile, PREFIX);		/* Set up name for my message file */
X	strncat(myfile, mytty, 5);
X	if (close(creat(myfile, 0)) == EOF);	/* Create message file */
X	chmod(myfile, 0644);
X
X	send(1);			/* Say hello to everyone */
X
X	dummy = gtty( 0, &Omode);
X	ttyset(1,0);			/* Set cbreak mode - no echo */
X	printf("Chat %s - press '?' for help.\r\n", VERSION);
X	who(0);				/* Show who's logged in Chat */
X
X	while(1)
X	{
X
X		inp = get();			/* Get a key */
X
X		switch(inp)			/* Check it */
X		{
X		case 'w':
X			who(0);
X			break;
X		case 'p':
X			if (page(1) == EOF)
X				fputs("Page(1) ML: unscuessful.\r\n",stderr);
X			break;
X		case 's':
X			send(0);
X			break;
X		case 'q':
X			quit();
X		case 'l':
X			if (page(0) == EOF)
X				fputs("Page(0) ML: unsuccessful.\r\n",stderr);
X			break;
X		case 'v':
X			printf("\r\nVer %s\r\n",VERSION);
X			break;
X		case '!':
X			shell();
X			break;
X		case '?':
X			cmds();
X			break;	
X		default:
X			readmsg();
X			break;
X		}
X	}
X}
X
Xget()	/* get char routine for chat,  waits 1 sec for input */
X	/*     (There's probably a better way to do it.)     */
X{
X	char ch;
X	int bye();
X
X	signal(SIGALRM,bye);
X
X	dummy = alarm(1);
X	ch = getchar() & 127;
X	dummy = alarm(0);
X
X	if ( ch < ' ' || ch > 'z' )
X		ch = 0;
X
X	if ( ch >= 'A' && ch <= 'Z' )
X		ch = ch + ( 'a' - 'A' ); 
X
X	return(ch);
X}
X
Xbye()	/* called if the alarm signal is caught */
X{
X	return(0);
X}
X
Xttyset(cbreak,echo)  	/* set tty to/from cbreak & echo mode */
X{
X	if (gtty( 0, &Nmode) == EOF) {
X		puts("No terminal");
X		exit(1);
X	}
X	if (cbreak) {
X		Nmode.sg_flags |= CBREAK;
X	} 
X	else {
X		Nmode.sg_flags &= ~CBREAK;
X	}
X	if (echo)
X		Nmode.sg_flags |= (ECHO | CRMOD);
X	else
X		Nmode.sg_flags &= ~(ECHO | CRMOD);
X
X	if (stty(0, &Nmode) == EOF) {
X		puts("Mode switch error.");
X		exit(1);
X	}
X}
X
X/* Page another user...for use with the chat system.  */
X/* calling this routine with a 1 will activate "page" */
X/* calling with a 0 will only call the print routine  */
X
X
Xpage(c)
X{
X
X
X	struct	utmp	ubuf;
X
X	FILE	*fp;
X	char	hisname[32],
X		_name[20][10],
X		*timein = "00:00am",
X		inp[256];
X	register int fd;
X	int i = 0, ttyn;
X
X
X	printf("\r\nUSERS LOGGED IN->\r\n");
X	if ((fd=open(FNAME, 0))== EOF) {
X		error("Page can't open /etc/utmp",1);
X		quit();
X	}
X
X	while (read(fd, (char *) &ubuf, sizeof(ubuf))==sizeof(ubuf)) {
X		if (ubuf.ut_line[0]=='\0' || ubuf.ut_name[0]=='\0')
X			continue;	/* skip unused entries */
X		strcpy(_name[i],ubuf.ut_name);
X		printf("Job%d %-8.8s %-7.7s in @ ", i+1,ubuf.ut_name, ubuf.ut_line);
X		prtime(localtime(&ubuf.ut_time), timein);
X		printf("%s\r\n", timein);
X		i++;
X	}
X
X	if(close(fd) == EOF)
X	{
X		error("Page can't close utmp.",1);
X		quit();
X	}
X
X				        /* page another user routine */
X	if (c == 0)
X		return(0);
X
X	ttyset(1, 1);			/* Turn on echo for input */
X	fputs("\nPage which job? [CR exits] ",stderr);
X	gets(inp);
X	ttyn = atoi(inp);
X
X	ttyset(1, 0);			/* All good things must be undone */
X	if (ttyn <= i && ttyn >= 1)
X	{
X		strcpy(hisname, PAGER);
X		strcat(hisname, _name[ttyn-1]);
X
X		if ((fp=popen(hisname,"w")) == NULL)
X		{
X			error("Unable to page user.",1);
X			ttyset(1, 0);
X			return(EOF);
X		}
X
X		fprintf(fp,">>YOU ARE BEING REQUESTED TO<<\n");
X                fprintf(fp,"       >>ENTER CHAT BY<<\n");
X		fprintf(fp,"--->%s -%s-\n", mixname, mytty);
X		fprintf(fp,"To enter type: /usr/slb/chat\n");
X
X		if (fclose(fp) == EOF)
X		{
X			error("Unable to close PAGER.",1);
X			quit();
X		}
X		printf("Page on it\'s way.  Please give %s enough time to respond.\r\n",_name[ttyn-1]);
X	}
X	return(0);
X}
X
Xprtime(tp, strng)	/* prtime returns the time in 12 hour format to strng */
Xstruct	tm	*tp;
Xchar	*strng;
X{
X	int	tim,
X		min,
X		pm;
X
X	tim = tp->tm_hour;		/* Set hours */
X	min = tp->tm_min;		/* Set mins  */
X	pm = (tim > 11);
X	if (tim > 11)
X		tim -= 12;
X	if (tim == 0)
X		tim = 12;
X	sprintf(strng, "%2d:%02d%s", tim, min, pm ? "pm" : "am");
X	return;
X}
X
Xcmds()	/* Print command list */
X{
X	puts("\r\n\
XThese are the available commands:\r\n\
X\r\n\
X(L)	Display users logged in.\r\n\
X(P)	Page a user.\r\n\
X(Q)	Exit chat session.\r\n\
X(S)	Send message.\r\n\
X(V)	Display version number.\r\n\
X(W)	See who's logged into Chat.\r\n\
X(!)	Execute shell command.\r\n\
X(?)	Print this menu.\r\n\
X");
X}
X
Xshell()		/* Read and execute a shell command */
X{
X	char	input[64];
X
X	ttyset(0,1);	/* back to normal */
X	fputs("\r\n!",stdout);
X	if (fgets(input, 64, stdin) == NULL);		/* If to humor lint */
X
X	if (system(input) == 127)
X		puts("EXECUTION ERROR\r");
X
X	puts("!\r");
X	ttyset(1,0);
X
X}
X
Xwho(f)		/* Show who's logged into chat */
Xint f;
X{
X
X	users = 0;
X
X	lseek(lfile, 0L, 0);
X	if (!f) {
X		puts("\r");
X		puts("Users In Chat        Tty    When\r");
X	}
X
X	while (read(lfile, (char *) &lbuf, sizeof(lbuf))==sizeof(lbuf)) {
X		if (lbuf.l_line[0]=='\0' || lbuf.l_name[0]=='\0')
X			continue;	/* Skip blankies */
X		if (users > MAXUSERS)
X			break;
X
X		sprintf(names[users].tty, "%5.5s", lbuf.l_line);
X		sprintf(names[users].uname, "%-20.20s", lbuf.l_name);
X		sprintf(names[users].intime, "%7.7s", lbuf.l_time);
X
X		if (!f)
X			printf("%-20.20s %-5.5s  %7.7s\r\n",lbuf.l_name,
X					  	    lbuf.l_line,lbuf.l_time);
X
X	users++;
X	}
X	return;
X}
X
Xquit()		/* Exit chat */
X{
X
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGHUP, SIG_IGN);
X
X	send(2);			/* Say goodbye */
X
X	if (unlink(myfile) == EOF)	/* Clear out msg file */
X		perror(myfile);
X
X	ttyset(0,1);			/* Back to normal */
X	puts("\n<*End of Chat Session*>");
X
X	if (ridname() == EOF) 		/* Take my name off the list */
X		exit(1);
X
X	who(1);				/* Check how many users */
X
X	if (close(lfile) == EOF) {	/* Close up the LOGFILE */
X		perror(LOGFILE);
X		exit(1);
X	}
X	if (!users) {
X		if (unlink(LOGFILE) == EOF) {
X			perror(LOGFILE);
X			exit(1);
X		}
X	}
X	exit(0);			/* Goodbye! */
X}
X
Xsend(o)		/* Send messages, 0=input, 1=login, 2=logout */
Xint o;
X{
X	int	i, t,
X		j = 0,	ch,
X		nusers = 0;
X	char	line[512],
X		*sname,
X		shrtname[6],
X		fname[64];
X
X	sname = mytty;
X	if (!strncmp(mytty, "tty", 3))
X		sname = mytty+3;
X
X	if (o == 0) {
X		fputs("\r\nTEXT> ",stdout);
X		for (i=0; i < 320; i = j) {
X			ch =  getchar();
X			if (ch == '\r' || ch >= ' ') {
X				j++;
X				line[i] = ch;
X				putchar(ch);
X				if (ch == '\r')  {
X					line[i] = '\0';
X					putchar('\n');
X					break;
X				}
X			} else if ((ch == '\b' || Omode.sg_erase) && j > 0) {
X				j--;
X				putchar(ch);
X			} else if (ch == '\t')  {
X				for (t=0; t<10; t++, j++) {
X					line[j] = ' ';
X					fputs(" ",stdout);
X				}
X			}
X		}
X	} else if (o == 1)
X		sprintf(line, "** %s logged in on %s **", myname, sname);
X	else
X		sprintf(line, "** %s logged out on %s **", myname, sname);
X
X/* File routine - appends message to all tty's except mine */
X
X	if (o == 0)
X		fputs("Sent to ",stdout);
X
X	lseek(lfile, 0L, 0);			/* Rewind */
X	while(read(lfile, (char *) &lbuf, sizeof(lbuf)) == sizeof(lbuf)) {
X
X		if (!strncmp(lbuf.l_line, mytty, 5))
X			continue;
X
X		strcpy(fname, PREFIX);
X		strncat(fname, lbuf.l_line, 5);
X
X		if (!strncmp(lbuf.l_line, "tty", 3))
X			strncpy(shrtname, lbuf.l_line+3, 2);
X		else
X			strncpy(shrtname, lbuf.l_line, 5);
X
X		if ((wfd=fopen(fname, "a")) == NULL) {
X			if (o == 0)
X				printf("*%-2.2s* ", shrtname);
X			continue;
X		} else
X			if (o != 0)
X				fprintf(wfd, "%s\n", line);
X			else {				
X				printf("%-2.2s ", shrtname);
X				fprintf(wfd, "<%s %s= %s>\n", sname, mixname, line);
X			}
X		nusers++;
X
X		if (fclose(wfd) == EOF) {
X			error("( send() )", 0);
X			quit();
X		}
X	}
X	if (o == 0) {
X		if (nusers == 0)
X			fputs("-Nobody", stdout);
X		fputs("\r\n", stdout);
X	}
X}
X
Xerror(estring,file)
Xchar	*estring;
X{
X
X	fputs("SYSTEM FILE ERROR",stderr);
X	if (file)
X		fprintf(stderr,"\r\n%s\r\n",estring);
X	else
X		fprintf(stderr," %s\r\n");
X}
X
Xreadmsg()
X{
X
X	int	ch;
X
X	if (stat(myfile, &sbuf) != EOF) 
X	if (sbuf.st_size != 0) {
X
X		if ((wfd=fopen(myfile, "r")) == NULL) {
X			error("readmsg(): can't open myfile",1);
X			quit();
X		}
X
X		while ((ch=getc(wfd)) != EOF) {
X			putchar(ch);
X			if (ch == '\n')
X				putchar('\r');
X		}
X
X		if (fclose(wfd) == EOF) {
X			error("readmsg(): closing error.",1);
X			quit();
X		}
X	if (fclose(fopen(myfile, "w")) == EOF);
X	}
X}
X
Xridname()	/* Get's rid of user, on mytty, in LOGFILE */
X{
X
X	lseek(lfile, 0L, 0);			/* Rewind file */
X
X	buffer[0] = '\0';
X	while(read(lfile, (char *) &lbuf, sizeof(lbuf)) == sizeof(lbuf)) {
X		if (strncmp(lbuf.l_line, mytty, 5) == NULL) 
X			continue;
X
X		strncat(buffer, lbuf.l_line, sizeof(lbuf.l_line));
X		strncat(buffer, lbuf.l_name, sizeof(lbuf.l_name));
X		strncat(buffer, lbuf.l_time, sizeof(lbuf.l_time));
X
X	}
X	strcat(buffer, "\0");
X
X	if ((wfd=fopen(LOGFILE, "w")) == NULL) {
X		perror(LOGFILE);
X		return(EOF);
X	}
X	fputs(buffer, wfd);
X
X	if (fclose(wfd) == EOF) {
X		perror(LOGFILE);
X		return(EOF);
X	}
X	return(NULL);
X}
X
Xsystem(s)
Xchar *s;
X{
X	int status, pid, w;
X	register int (*istat)(), (*qstat)();
X
X	if ((pid = fork()) == 0) {
X		setuid(getuid());
X		execl("/bin/sh", "sh", "-c", s, 0);
X		_exit(127);
X	}
X	istat = signal(SIGINT, SIG_IGN);
X	qstat = signal(SIGQUIT, SIG_IGN);
X	while ((w = wait(&status)) != pid && w != -1)
X		;
X	if (w == -1)
X		status = -1;
X	signal(SIGINT, istat);
X	signal(SIGQUIT, qstat);
X	return(status);
X}
/
echo 'x - chat.h'
sed 's/^X//' > chat.h << '/'
X/*	This file contains all the major variables for the Chat		*/
X/*	system.		->slb@bnl.ARPA					*/
X/* chat.h :-: 2/6/85 */
X
X#define SYSTEMFILE "/usr/lib/chat_sfile"
X#define PREFIX	"/tmp/ct."		/* Storage for messages */
X#define	FNAME	"/etc/utmp"		/* To see who's on the system */
X#define PAGER	"/bin/mail "		/* Media for paging */
X#define	LOGFILE	"/lib/chat_log"		/* List of users in chat */
X#define MAXUSERS 10			/* Max # of users in chat */
X
Xstruct logs {
X	char	l_line[5];		/* tty name */
X	char	l_name[20];		/* username & handle */
X	char	l_time[7];		/* time in */
X};
X
/
echo 'x - cwho.c'
sed 's/^X//' > cwho.c << '/'
X#include <stdio.h>
X#include "chat.h"
X
Xstruct logs	lbuf;
X
Xmain()		/* Show who's logged into chat */
X{
X	int 	nusers = 0;
X	int	lfile;
X
X	if ((lfile=open(LOGFILE, 0)) == EOF)
X		exit(1);
X
X	puts("Users In Chat        Tty    When");
X
X	while (read(lfile, (char *) &lbuf, sizeof(lbuf))==sizeof(lbuf)) {
X		if (lbuf.l_line[0]=='\0' || lbuf.l_name[0]=='\0')
X			continue;	/* Skip blankies */
X
X	printf("%-20.20s %-5.5s  %7.7s\n",lbuf.l_name,
X					  	   lbuf.l_line,lbuf.l_time);
X
X	nusers++;
X
X	}
X	if (close(lfile) == EOF) {
X		perror(LOGFILE);
X		exit(1);
X	}
X}
/
echo 'x - ruser.c'
sed 's/^X//' > ruser.c << '/'
X/*  Remove a pesky luser from the chat system.	*/
X/*  To use type: riduser tty##			*/
X
X#include <stdio.h>
X#include "chat.h"
X
Xstruct logs	lbuf;
X
Xmain(argc, argv)		/* Get's rid of user, on mytty, in logfile */
Xint argc;
Xchar *argv[];
X{
X	char	*buffer = "\0";
X	int	lfile;
X	FILE	*fp;
X
X	if (argc != 2) {
X		fputs("ruser: arg count\n", stderr);
X		exit(1);
X	}
X
X	if ((lfile=open(LOGFILE, 0)) == EOF) {
X		puts("No users in logfile");
X		exit(1);
X	}
X
X	while(read(lfile, (char *) &lbuf, sizeof(lbuf)) == sizeof(lbuf)) {
X		if (strncmp(lbuf.l_line, argv[1], 5) == NULL) 
X			continue;
X
X		strncat(buffer, lbuf.l_line, sizeof(lbuf.l_line));
X		strncat(buffer, lbuf.l_name, sizeof(lbuf.l_name));
X		strncat(buffer, lbuf.l_time, sizeof(lbuf.l_time));
X
X	}
X
X	if (close(lfile) == EOF) {
X		perror(LOGFILE);
X		exit(1);
X	}
X	if ((fp=fopen(LOGFILE, "w")) == NULL) {
X		perror(LOGFILE);
X		exit(1);
X	}
X
X	fputs(buffer, fp);
X
X	if (fclose(fp) == EOF) {
X		perror(LOGFILE);
X		exit(1);
X	}
X}
/
echo 'Part 01 of Chat complete.'
exit

-- 
                        Sanford L. Barr
           Famous designer of the Write Only Memory.
                       --             --
		..!decvax!philabs!sbcs!bnl!slb

dab1@ahutb.UUCP (dab1) (02/25/85)

So far I have had 2 problems compiling chat.
Note that I am using the standard bourne shell.

"CBREAK" does not seem to be in sgetty.h or in any /usr/include file.

As shown below:

$ make

	cc chat.c -O -o chat
*** Error code 1
"chat.c", line 244: CBREAK undefined
"chat.c", line 247: CBREAK undefined

Stop.
	cc chat.c -O -o chat


And with that commented out it seems that rindex is undefined.
$ make

*** Error code 13
undefined		first referenced
 symbol  		    in file
rindex              		chat.o
ld fatal: Symbol referencing errors. No output written to chat

Stop.

Thanx in advance;

David Berk
ATT-ISL