Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site bnl44.UUCP Path: utzoo!linus!philabs!sbcs!bnl44!slb From: slb@bnl44.UUCP (Sanford L. Barr @ Brookhaven National Labs. Long Island, N.Y.) Newsgroups: net.sources Subject: Chat - A multi user communications package Message-ID: <1009@bnl44.UUCP> Date: Wed, 25-Sep-85 23:48:39 EDT Article-I.D.: bnl44.1009 Posted: Wed Sep 25 23:48:39 1985 Date-Received: Fri, 27-Sep-85 07:31:44 EDT Distribution: net Lines: 1556 (Watch for signature) #!/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. * # ***************************************************************************** # * * # * Chat Version 6.0 * # * * # * This is a copy of the Chat system developed at Brookhaven * # * National Labs (Later drastically improved at my house) to allow a * # * group conversation between users. * # * * # * A very early version of this program was released a while * # * ago and I apologize to all the non-V7 people who struggled with it. * # * This version (6.0) was developed on both a PDP-11/44 and an AT&T * # * UNIX PC. So, I can almost guarentee no problems with sysV or V7. * # * For 4.x BSD there should be little or no modifications to make. * # * * # * 6.0 adds a few goodies like wordwrap, accessing of the termcap * # * library for special functions, and an overall enhancement in the way it * # * works. * # ***************************************************************************** # Files included are: # # Makefile # README Read this for some insight. # README2 Read this to get started. # chat.h # chat.1 Manual page for chat system. # cursub.c # cwho.c C-source for the cwho command (similar to who(1)) # defs.h Easy access list of major Chat variables. # main.c # misc.c # page.c # quit.c # readmsg.c # ruser.c C-source for the remove user system utility. # send.c # ttyset.c # # Sanford L. Barr | slb\@bnl44.ARPA # 39 Royalston Lane | slb\@bnl44.UUCP # S. Setauket, N.Y. 11720 # (516) 736-4155 (home) # # Please send me any updates that you may make, especially regarding # 4.x BSD. Thanks. # ______ # This program, with permission from the author, is being posted as a favor # to the UN*X community. In no way may this material be reproduced in any # other way, shape or form other than electronic mail, without written # permission from the author. Any use of this program or any part thereof # other than for non-profit also requires written permission from the author. # *************************************************************************** # echo 'Start of Chat.shar, part 01 of 01:' echo 'x - Makefile' sed 's/^X//' > Makefile << '/' X############################################################################### X#### Makefile for The Chat System by SLB #### X############################################################################### XCC=cc X X############################################################################### X# The DESTDIR is the final location of the compiled chat system along with X# All commands (cwho, ruser) XDESTDIR=/usr/local/bin X X############################################################################### X# OWNER and GROUP are the names of the owner and group of the chat system X# (usually bin bin or whoever decides to oversee Chat) XOWNER=bin XGROUP=bin X X############################################################################### X# MANDIR is where the manual page for chat is to be stored (if at all). XMANDIR=/usr/man/man1 X X############################################################################### X# Defined flags: X# If your system has TERMIO then define it, otherwise Chat assumes you have X# CBREAK mode in sgtty.h X# Define ENEMY if you wish to be able to "squelch" users who abuse their X# Chat privledges (see README). X# Define VOID if your system has the void type. X# Define INDEX if your system has INDEX insted of STRCHR XCFLAGS= -Os -DTERMIO -DINDEX -DENEMY -DVOID X XOBJECTS= main.o cursub.o ttyset.o page.o readmsg.o send.o misc.o quit.o X Xall: chat cwho ruser X Xchat: chat.h $(OBJECTS) defs.h X $(CC) -Os $(OBJECTS) -o chat -ltermlib X Xcwho: defs.h cwho.c X $(CC) -Os cwho.c -o cwho X Xruser: defs.h ruser.c X $(CC) -Os ruser.c -o ruser X Xlint: X lint -bxa *.c X Xinstall: X mv chat ${DESTDIR} X chown ${OWNER} ${DESTDIR}/chat X chgrp ${GROUP} ${DESTDIR}/chat X chmod ug+s ${DESTDIR}/chat X mv cwho ${DESTDIR} X mv ruser ${DESTDIR} X chown ${OWNER} ${DESTDIR}/ruser X chgrp ${GROUP} ${DESTDIR}/ruser X chmod ug+s ${DESTDIR}/ruser X mv chat.1 ${MANDIR} X Xclean: X rm -f ${OBJECTS} / echo 'x - README' sed 's/^X//' > README << '/' XFiles included in this directory are as follow: X X main.c misc.c page.c ttyset.c cursub.c send.c readmsg.c X X These files are the source code for the chat system. After XChat 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 defs.h) X X defs.h X X This file contains all the major Chat system variables. Included Xare: X 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 following comments). X X chat.1 X X Manual page for Chat. Formatted in man macros. 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 has only Xhappened once during he duration of Chat's development. But I included Xthe utility just in case. X------ 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 case 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 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 - README2' sed 's/^X//' > README2 << '/' XTo get Chat up and running: X X #1 unpack and rummage through the Makefile. Tailor it to your X needs. X X #2 Edit and change "defs.h" to suit your particular system. X X #3 Type "make" and sit back and watch the fun. X XIf you defined what you wanted the makefile to do for installation type X"make install" and that will move Chat, and it's subprograms, to the Xdestination directory. Along with changing it to the correct permissions. X XOther important stuff is in README2. / echo 'x - chat.1' sed 's/^X//' > chat.1 << '/' X.TH CHAT 1 X.SH NAME Xchat \- Chat with up to 10 users X.PP Xcwho \- See who\'s logged into Chat. X.SH SYNOPSIS X.B chat X.PP X.B cwho X.SH DESCRIPTION X.I Chat, Xis a multi-user communications system Xwhich 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 Xterminated by "<" and include the sender's name, handle, and tty. A Xstandard message would look something like this: X X05 joeluser(Handle)= This is a test message.< X XAs of revision 6.0, X.I Chat Xnow includes wordwrap along with formatting the incoming messages to line Xup with the "="'s. This gives a much more desirable effect and aleviates the Xproblem with terminals that do not have linewrap. 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 environment variable XHANDLE and defining it to their preference (up to 10 characters). XFrom sh(1) this can be done by typing: X X$ HANDLE="Your Handle Here"; export HANDLE X XFrom csh(1): X X% setenv HANDLE "Your Handle Here" X X.TP X.I L 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 X.I P 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 X.I S 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 X.I W XDisplay all users logged into Chat. X.PP XThis command displays the name, handle, time and tty of all users Xcurrently logged into the Chat system. X.TP X.I Q 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.I ! 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 flood the user's terminal upon re-entry to Xcommand returns control to X.I Chat. X.TP X.I ? XPrint a command summary. X.PP XThis command will print a brief summary of all current X.I Chat Xcommands. X.TP X.I cwho(1) X.PP XCwho is essentially a short program which allows a user who's not in the current Xchat session to get a listing of the people in it. X.I Cwho Xrequires no arguments and exits with "No users logged into Chat" if no-one Xis currently in X.I chat. X.I cwho\'s Xoutput is essentially identical to that of the X.I chat Xcommand "W". X.PP XAll signals received by X.I Chat X, 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/CHATLOG log of user's in current chat session X.SH "SEE ALSO" Xmail(1) X.SH BUGS XUser's handles are left up to their imagination. X XChat doesn't seem to react well to users logged in as root. / 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 :-: 9/19/85 */ X X#include /* All those .h files! */ X#include "defs.h" X#include X#include X#include X#include X#include X#include X X#define ON 1 X#define OFF 0 X#define OK 0 X#define FERROR 0 X#define ERR (-1) X#define INLEN (80 * 4) /* Max number of chars input */ X X#ifndef VOID X#define void int X#endif X Xstruct stat sbuf; Xstruct logs lbuf; X Xextern char /* String Function Defs */ X *strcpy(), X *strncpy(), X *strcat(), X *strncat(), X *strtok(), X#ifdef INDEX X *rindex(), X *index(); X#else X *strrchr(), X *strchr(); X#endif INDEX X Xchar mytty[6], /* User's tty */ X myname[16], /* Username */ X mixname[32], /* Both uname and handle */ X myfile[64], /* User message file */ X buffer[512]; X Xint quit(), X bye(), X length, /* Length of ttyname */ X lfile; /* Descriptor for LOGFILE */ X Xunsigned int users; /* No of users in Chat */ X Xlong time(), X lseek(); X Xunsigned alarm(); X XFILE *wfd; X Xvoid exit(),perror(), X _exit(), qsort(); X X/* Termcap Stuff */ Xextern char *BC, *CM, *CL, *tgoto(), X *CE, *SO, *SE, *CD, X *TI, *TE; Xextern int CO, LI; / echo 'x - cursub.c' sed 's/^X//' > cursub.c << '/' X/* cursub.c :=: 9/25/85 By SLB */ X X/* Various cursor subroutines to add nice touches to Chat */ X#include "chat.h" X X#define NULLCHAR ((char *)0) X#define CR 015 X Xchar *BC, *CM, *CL, *CE, *SO, *SE; Xchar *CD, *TI, *TE; Xint CO, LI; X Xchar tspace[512], *bufspace; Xchar *tgetstr(), *getenv(); Xint putch(); X Xcinit() X{ X char bbuf[1024]; X char *tgoto(); X char *TERM; X X if ((TERM=getenv("TERM")) == FERROR) X TERM = "dumb"; X X tgetent (bbuf, TERM); X bufspace = tspace; X CM = tgetstr ("cm", &bufspace); X CL = tgetstr ("cl", &bufspace); X BC = tgetstr ("bc", &bufspace); X if (BC == NULLCHAR || tgetflag("bs")) X BC = "\b"; X CO = tgetnum ("co"); X LI = tgetnum ("li"); X SO = tgetstr ("so", &bufspace); X SE = tgetstr ("se", &bufspace); X CD = tgetstr ("cd", &bufspace); X TI = tgetstr ("ti", &bufspace); X TE = tgetstr ("te", &bufspace); X X if (SO == NULLCHAR) X SO = ""; X if (SE == NULLCHAR) X SE = ""; X if (CM == NULLCHAR) X return 1; X return 0; X} X Xhilight(str) Xchar *str; X{ X tputs(SO, 0, putch); X fputs(str, stdout); X tputs(SE, 0, putch); X} X X/* Move cursor to specified spot. (1,1) upper left. (80,24) lower right */ X Xmvcur(x, y) Xint x, y; X{ X tputs (tgoto (CM, x-1, y-1), 0, putch); X} X X/* Clear screen */ Xclear() X{ X int i; X X if (CL) { X tputs(CL, 0, putch); X putch(CR); X } X mvcur(1,1); X} X X/* Erase current line */ Xzapline() X{ X if (CE) { X putch('\r'); X tputs(CE, 0, putch); X } else X puts("\r"); X} / echo 'x - cwho.c' sed 's/^X//' > cwho.c << '/' X/* cwho.c :=: 9/25/85 By SLB */ X X#include X#include X#include X#include "defs.h" X Xstruct logs lbuf; Xstruct stat sbuf; X Xmain() /* Show who's logged into chat */ X{ X int lfile; X X if (stat(LOGFILE, &sbuf) == EOF || sbuf.st_size == 0) { X puts("No users logged into Chat."); X exit(0); X } X X if ((lfile=open(LOGFILE, 0)) == EOF) { X perror(LOGFILE); X exit(1); X } 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 !strncmp(lbuf.l_name, "LOGIN", 5)) 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 } X if (close(lfile) == EOF) { X perror(LOGFILE); X exit(1); X } X} / echo 'x - defs.h' sed 's/^X//' > defs.h << '/' X/* Chat System Definition Header File */ X/* ->slb\@bnl.ARPA */ X/* chat.h :-: 9/19/85 */ X X#define SYSTEMFILE "/usr/slb/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 " /* Medium for paging */ X#define LOGFILE "/usr/slb/CHATLOG" /* List of users in chat */ X#define MAXUSERS 10 /* Max # of users in chat */ X Xstruct logs { X char l_line[5]; /* User's tty */ X char l_name[20]; /* User's name and handle */ X char l_time[7]; /* Entered chat */ X} Xnames[MAXUSERS]; / echo 'x - header' sed 's/^X//' > header << '/' X*This is a shell archive. Remove anything before this line and run the rest* X*of this file through the 'sh' command. Or use the 'unshar' command. * X***************************************************************************** X* * X* Chat Version 6.0 * X* * X* This is a copy of the Chat system developed at Brookhaven * X* National Labs (Later drastically improved at my house) to allow a * X* group conversation between users. * X* * X* A very early version of this program was released a while * X* ago and I apologize to all the non-V7 people who struggled with it. * X* This version (6.0) was developed on both a PDP-11/44 and an AT&T * X* UNIX PC. So, I can almost guarentee no problems with sysV or V7. * X* For 4.x BSD there should be little or no modifications to make. * X* * X* 6.0 adds a few goodies like wordwrap, accessing of the termcap * X* library for special functions, and an overall enhancement in the way it * X* works. * X***************************************************************************** X Files included are: X XMakefile XREADME Read this for some insight. XREADME2 Read this to get started. Xchat.h Xchat.1 Manual page for chat system. Xcursub.c Xcwho.c C-source for the cwho command (similar to who(1)) Xdefs.h Easy access list of major Chat variables. Xmain.c Xmisc.c Xpage.c Xquit.c Xreadmsg.c Xruser.c C-source for the remove user system utility. Xsend.c Xttyset.c X XSanford L. Barr | slb\@bnl44.ARPA X39 Royalston Lane | slb\@bnl44.UUCP XS. Setauket, N.Y. 11720 X(516) 736-4155 (home) X X Please send me any updates that you may make, especially regarding X4.x BSD. Thanks. X______ XThis program, with permission from the author, is being posted as a favor Xto the UN*X community. In no way may this material be reproduced in any Xother way, shape or form other than electronic mail, without written Xpermission from the author. Any use of this program or any part thereof Xother than for non-profit also requires written permission from the author. X*************************************************************************** / echo 'x - main.c' sed 's/^X//' > main.c << '/' X/* Chat ver 6.0 */ X/* Written by Sanford L. Barr (slb\@BNL44.ARPA) */ X/* misc.c :=: 9/25/85 */ X#define VERSION "6.0 by SLB" X X/**************************** X** CHAT ** X** ** X** A multi-user ** X** communication system ** X****************************/ X X#include "chat.h" X Xint cptty(a, b) /* Compare routine for qsort */ Xstruct logs *a, *b; X{ X return(strcmp(a->l_line, b->l_line)); X} X Xmain() X{ X char inp, X *getlogin(), X *getenv(), X *ttyname(), X *temptty = "\0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", X *handle = "(\0xxxxxxxx", X login[8], /* Time entered chat */ 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 X cinit(); /* Initalize cursor routines */ X temptty = ttyname(2); /* Get tty */ X#ifdef INDEX X temptty = rindex(temptty,'/') + 1; X#else X temptty = strrchr(temptty,'/') + 1; X#endif X sprintf(mytty, "%5.5s", temptty); /* Truncate */ X length = strlen(mytty); X strcpy(myname, getlogin()); /* Get username */ X junk = &jline[0]; X X ti = time(0); X prtime(ti,login); /* Set login time */ X X if ((wfd=fopen(SYSTEMFILE,"r")) != FERROR) { /* Squelch users */ X for(;;) { X if (fgets(junk, 32, wfd) == OK) 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#ifdef ENEMY 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#endif X if (i) X break; X } X if (fclose(wfd) == ERR) { X perror(SYSTEMFILE); X exit(1); X } X } X junk = &jline[0]; X strcpy(mixname, myname); /* Get handle and */ X if ((junk=getenv("HANDLE")) != FERROR) {/* Add it to mixname */ X strncat(handle, junk, 10); X strcat(handle,")"); X strncat(mixname, handle, strlen(handle)); X } X X s = 3; X while (s++ < 19) /* Catch signals and */ X if ((s != 18) && (s != SIGALRM))/* ignore them. */ X signal(s, SIG_IGN); X X signal(SIGHUP, quit); /* These signals get */ X signal(SIGINT, quit); /* sent to quit */ X signal(SIGQUIT,quit); X X if (access(LOGFILE, 00) != OK) { X close(creat(LOGFILE, 0644)); /* Create logfile */ X chmod(LOGFILE, 0644); X } X X if((lfile=open(LOGFILE, 0)) == FERROR) { /* Open logfile */ X perror(LOGFILE); X exit(1); X } X X if (ridname() == ERR) /* Clear out dead users */ X exit(1); /* if any */ X X who(ON, OFF); /* 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].l_line, "%5.5s", mytty); X sprintf(names[users].l_name, "%-20.20s", mixname); X sprintf(names[users].l_time, "%7.7s", login); X X qsort((char *) names, users+1, sizeof(*names), cptty); /* Sort tty's */ X X if ((wfd=fopen(LOGFILE,"w")) == FERROR) { X error("Couldn\'t open LOGFILE", ON); 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].l_line, X names[l].l_name, names[l].l_time); X X if (fclose(wfd) == ERR) { 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)) == ERR); /* Create message file */ X chmod(myfile, 0644); X X send(1); /* Say hello to everyone */ X X tstore(); /* Save terminal settings */ X X ttyset(ON,OFF); /* Set cbreak mode - no echo */ X X clear(); /* Clear Screen */ X printf("\r\nChat %s - press '?' for help.\r\n", VERSION); X who(OFF, OFF); /* Show who's logged in Chat */ X X while(ON) X { X X inp = get(); /* Get a key */ X X switch(inp) /* Check it */ X { X case 'w': X who(OFF, ON); X break; X case 'p': X if (page(ON) == ERR) X fputs("Page(ON) ML: unsucessful.\r\n", stderr); X break; X case 's': X send(0); X break; X case 'q': X quit(); X case 'l': X if (page(OFF) == ERR) X fputs("Page(OFF): unsucessful.\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 X signal(SIGALRM, bye); X X alarm(ON); X ch = getchar() & 127; X alarm(OFF); X X if (!isprint(ch)) X ch = 0; X else X if (isupper(ch)) X ch = tolower(ch); X X return(ch); X} X Xbye() /* called if the alarm signal is caught */ X{ X return; X} X / echo 'x - misc.c' sed 's/^X//' > misc.c << '/' X/********************* X** Chat ** The Chat System by SLB X** Miscellaneous ** X** Subroutines ** Revision 6.0 X** ** X** prtime() ** September 18, 1985 X** who() ** X** ridname() ** X** cmds() ** (misc.c - Written by Sanford L. Barr) X** putch() ** X** shell() ** X** error() ** X** sysexec() ** X**********************/ X X#include "chat.h" X Xprtime(ti, strng) /* prtime returns the time in 12 hour format to strng */ Xchar *strng; Xlong ti; X{ X struct tm *tp; X struct tm *localtime(); X int tim, X min, X pm; X X tp = localtime(&ti); 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 char input; X X clear(); /* Clear Screen */ X puts("\r\n\r\n\r\n\ X------------------------------------\r\n\ X------Chat System Command List------\r\n\ X------------------------------------\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 via mail(1). -\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(!sh) Escape to shell. -\r\n\ X(?) Print this menu. -\r\n\ X------------------------------------\r\n\ X"); X hilight("Press [Return] to Continue:"); X input = getchar(); X clear(); X return; X} X Xputch(ch) /* output a character */ Xint ch; X{ X putchar(ch); X} X Xshell() /* Read and execute a shell command */ X{ X char input[80], X chr; X X ttyset(OFF,ON); /* back to normal */ X fputs("\r\nSuspending Chat: Enter command and hit return\r\n!",stdout); X fgets(input, 80, stdin); X X if (sysexec(input) == 127) X puts("EXECUTION ERROR: Can't generate a shell\r"); X X ttyset(ON,OFF); /* Cbreak again */ X hilight("Press [Return] to Resume Chat:"); X chr = getchar(); X clear(); /* Clear Screen */ X} X Xwho(f, cl) /* Show who's logged into chat */ Xint f, cl; X{ X X users = 0; X X lseek(lfile, 0L, 0); /* Rewind LOGFILE */ X if (!f) { X if (cl) X clear(); /* Clear Screen */ X puts("\r\n\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].l_line, "%5.5s", lbuf.l_line); X sprintf(names[users].l_name, "%-20.20s", lbuf.l_name); X sprintf(names[users].l_time, "%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 if (!f) X puts("\r"); X return; 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 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, length)) 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")) == FERROR) { X perror(LOGFILE); X return(ERR); X } X fputs(buffer, wfd); X X if (fclose(wfd) == ERR) { X perror(LOGFILE); X return(ERR); X } X return(OK); X} X Xsysexec(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} X / echo 'x - page.c' sed 's/^X//' > page.c << '/' X/* page.c :=: 9/25/85 by SLB */ 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#include "chat.h" X Xpage(c) X{ X X X struct utmp ubuf; X X FILE *fp; X char hisname[32], X _name[20][11], X *timein = "00:00am", X inp[256]; X int fd; X int i = 0, ttyn; X X X clear(); /* Clear Screen */ X printf("\r\n\r\n\r\nUSERS LOGGED IN->\r\n"); X if ((fd=open(FNAME, 0))== ERR) { X error("Page can't open /etc/utmp", ON); 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 || !strcmp(ubuf.ut_name, "LOGIN")) X continue; /* skip unused entries */ X strcpy(_name[i],ubuf.ut_name); X prtime(ubuf.ut_time, timein); X printf("Job%d %-8.8s %-7.7s in \@ %s\r\n", i+1, X ubuf.ut_name, ubuf.ut_line, timein); X i++; X } X X if(close(fd) == ERR) X { X error("Page can't close utmp.", ON); X quit(); X } X X /* page another user routine */ X if (c == 0) X return(OK); X X fputs("\nPage which job? [CR exits] ", stdout); X ttyset(OFF,ON); /* Turn on echo for input */ X X gets(inp); X ttyn = atoi(inp); X X ttyset(ON,OFF); /* All good things must be undone */ X X if (ttyn <= i && ttyn >= 1) X { X strcpy(hisname, PAGER); X strcat(hisname, _name[ttyn-1]); X X if ((fp=popen(hisname,"w")) == FERROR) X { X error("Unable to page user.", ON); X return(ERR); X } X X fprintf(fp,"\n>>YOU ARE BEING REQUESTED TO<<\n"); X fprintf(fp," >>ENTER CHAT BY<<\n"); X fprintf(fp,"--->%s -%s-\n", mixname, mytty); X X if (fclose(fp) == ERR) X { X error("Unable to close PAGER.", ON); X quit(); X } X printf("Page on it\'s way. Please give %s enough time to respond.\r\n",_name[ttyn-1]); X } else X puts("No page sent.\r"); X return(0); X} X X / echo 'x - quit.c' sed 's/^X//' > quit.c << '/' X/* QUIT - Written By Sanford L. Barr for the Chat System 1985 */ X/* quit.c :=: 9/25/85 */ X X#include "chat.h" 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) == ERR) /* Clear out msg file */ X perror(myfile); X X trestore(); /* Back to normal */ X X puts("\n<*End of Chat Session*>"); X X if (ridname() == ERR) /* Take my name off the list */ X exit(1); X X X if (close(lfile) == ERR) { /* Close up the LOGFILE */ X perror(LOGFILE); X exit(1); X } X if (stat(LOGFILE, &sbuf) == ERR) { X perror(LOGFILE); X exit(1); X } X if (sbuf.st_size == 0) { X if (unlink(LOGFILE) == ERR) { X perror(LOGFILE); X exit(1); X } X } X exit(OK); /* Goodbye! */ X} X / echo 'x - readmsg.c' sed 's/^X//' > readmsg.c << '/' X/* readmsg.c :=: 9/25/85 By SLB */ X X#include "chat.h" X X#define STARTTXT '=' X#define LOGMSG '*' X#define ENDTXT '<' X#define READLEN INLEN + 50 /* Max number of chars input */ X Xint CO; X Xreadmsg() X{ X char linebuf[READLEN]; X X if (stat(myfile, &sbuf) == ERR) X return; X if (sbuf.st_size == 0) X return; X X if ((wfd=fopen(myfile, "r")) == FERROR) { X error("readmsg(): can't open myfile", ON); X quit(); X } X X while (fgets(linebuf, READLEN, wfd) != NULL) X wordwrap(linebuf); X X if (fclose(wfd) == ERR) { X error("readmsg(): closing error.", ON); X quit(); X } X close(creat(myfile, 0644)); /* Wipe out file */ X} X Xwordwrap(s) /* Wordwrap s to output */ Xchar *s; X{ X int buflen, tmplen, cmplen; X int indent; X X char buffer[800], X temp[40], X *ptr; X X cmplen = CO - 1; X /* Check possible text types */ X#ifdef INDEX X if ((s[0] == LOGMSG) || ((ptr=index(s, STARTTXT)) == NULL)) { X#else X if ((s[0] == LOGMSG) || ((ptr=strchr(s, STARTTXT)) == NULL)) { X#endif INDEX X fputs(s, stdout); X fputs("\r", stdout); X return; X } X X indent = strlen(s) - strlen(ptr) + 2; /* Get message indent */ X X strcpy(buffer, ""); X X while(strip(s, temp) != EOF) { X buflen = strlen(buffer); X tmplen = strlen(temp); X if ((buflen + tmplen) < cmplen) { X strcat(buffer, temp); X } else { X buflen = strlen(buffer); X cmplen = buflen + CO + 2; X strcat(buffer, "\r\n"); X strncat(buffer, " ", indent); X strcat(buffer, temp); X } X } X fputs(buffer, stdout); X puts("\r"); X} X Xstrip(str, outstr) /* Break string into words 20 chars or less */ Xchar *str, *outstr; X{ X int i, j; X X for (i=0,j=0; j < 20 && (str[i] != ' ' && str[i] != '\n'); i++, j++) { X outstr[j] = str[i]; X if (str[i] == '\0') X return(EOF); X } X if (str[i] != '\n') X outstr[j++] = str[i]; X outstr[j] = '\0'; X strcpy(str, &str[i+1]); X return; X} / echo 'x - ruser.c' sed 's/^X//' > ruser.c << '/' X/* ruser.c :=: 9/25/85 By SLB */ X X/* Remove a pesky luser from the chat system. */ X/* To use type: riduser ttyname */ X X#include X#include "defs.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("usage: ruser \n", stderr); X exit(1); X } X X if ((lfile=open(LOGFILE, 0)) == EOF) { X puts("No users in logfile."); X exit(0); 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 X if (strlen(buffer) == 0) { X unlink(LOGFILE); X exit(0); X } 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 'x - send.c' sed 's/^X//' > send.c << '/' X/* send.c :=: 9/25/85 By SLB */ X X#include "chat.h" X Xsend(o) /* Send messages, 0=input, 1=login, 2=logout */ Xint o; X{ X int i = 0, X t, ch, X nusers = 0; X char line[512], X *sname, X shrtname[5], X fname[64]; X X sname = mytty; X if ((!strncmp(sname, "tty", 3)) || (!strncmp(sname, " ", 3))) X sname = sname+3; X X if (o == 0) { X fputs("\r\nTEXT> ",stdout); X while (ON) { X ch = getchar(); X if ((i + 1 > INLEN) && ((ch != '\r') && (ch != '\n') && (ch != '\b'))) { X putchar('\007'); X continue; X } X if ((ch == '\b') && i > 0) { X i--; X fputs("\b \b", stdout); X continue; X } else if (isprint(ch) || (isspace(ch) && ch != '\t')) { X line[i] = ch; X putchar(ch); X if (ch == '\n' || ch == '\r') X if (i > 0) { X line[i] = '\0'; X putchar('\n'); X break; X } else { X zapline(); X puts("Aborted\r"); X return; X } X i++; 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/* Note: This system is not perfect. All devicenames throughout Xthe program get truncated to 5 chars which could cause trouble with Xsystems that have long and similar devicenames. */ X 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, length)) X continue; X X strcpy(fname, PREFIX); X strncat(fname, lbuf.l_line, 5); X X strncpy(shrtname, lbuf.l_line, 5); X if ((!strncmp(shrtname,"tty",3))||(!strncmp(shrtname," ", 3))) X strcpy(shrtname, &shrtname[3]); X X if ((wfd=fopen(fname, "a")) == FERROR) { 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("%-.5s ", shrtname); X fprintf(wfd, "%s %s= %s<\n", X sname, mixname, line); X } X nusers++; X X if (fclose(wfd) == ERR) { X error("( send() )", OFF); X quit(); X } X } X if (o == 0) { X if (nusers == 0) X fputs("-Nobody", stdout); X puts("\r"); X } X} X / echo 'x - ttyset.c' sed 's/^X//' > ttyset.c << '/' X/* ttyset.c :=: 9/25/85 By SLB */ X X#include "chat.h" X X#ifdef TERMIO X# include X#else X# include X# include X#endif X X#ifdef TERMIO X struct termio Nmode, Omode; X#else X struct sgttyb Nmode, Omode; X#endif X Xttyset(cbreak,echo) /* set tty to/from cbreak & echo mode */ X{ X#ifdef TERMIO X if (ioctl(0, TCGETA, &Nmode) == ERR) { X#else X if (ioctl(0, TIOCGETP, &Nmode) == ERR) { X#endif TERMIO X puts("No terminal"); X exit(1); X } X if (cbreak) { X#ifdef TERMIO X Nmode.c_lflag &= ~ICANON; X Nmode.c_cc[VMIN]=1; X Nmode.c_cc[VTIME]=0; X#else X Nmode.sg_flags |= CBREAK; X#endif TERMIO X } else { X#ifdef TERMIO X Nmode.c_lflag |= ICANON; X Nmode.c_cc[VEOF]=CEOF; X Nmode.c_cc[VEOL]=CNUL; X#else X Nmode.sg_flags &= ~CBREAK; X#endif TERMIO X } X X if (echo) X#ifdef TERMIO X Nmode.c_lflag |= ECHO; X#else X Nmode.sg_flags |= (ECHO | CRMOD); X#endif TERMIO X else X#ifdef TERMIO X Nmode.c_lflag &= ~ECHO; X#else X Nmode.sg_flags &= ~(ECHO | CRMOD); X#endif TERMIO X X#ifdef TERMIO X if (ioctl(0, TCSETA, &Nmode) == ERR) { X#else X if (ioctl(0, TIOCSETP, &Nmode) == ERR) { X#endif TERMIO X puts("Mode switch error."); X exit(1); X } X} X Xtstore() /* Store previous terminal settings */ X{ X#ifdef TERMIO X if (ioctl(0, TCGETA, &Omode) == ERR) { X#else X if (ioctl(0, TIOCGETP, &Omode) == ERR) { X#endif TERMIO X fputs("No terminal.",stderr); X quit(); X } X} X Xtrestore() /* Restore previous terminal settings */ X{ X X#ifdef TERMIO X if (ioctl(0, TCSETA, &Omode) == ERR) X#else X if (ioctl(0, TIOCSETP, &Omode) == ERR) X#endif TERMIO X fputs("Mode switch error.",stderr); X} / echo 'Part 01 of Chat.shar complete.' exit -- Sanford L. Barr Famous designer of the Write Only Memory. -- -- ..!decvax!mcnc!philabs!sbcs!bnl44!slb ...slb@bnl44.ARPA ...slb@bnl44.UUCP Voice phone: (516) 736-4155 Address (USnail): Almagmated Tech. 39 Royalston La. S. Setauket, N.Y. 11720 ATTN: Sanford L. Barr Brought to you by Super Global Mega Corp .com