Party - A multi user rap program for SysV

John C. Sucilla jcs at tarkus.UUCP
Mon Oct 17 05:00:39 AEST 1988


Theres been quite a few people asking for multi user talk/write type programs
the last few months so I figured I'd let this one out finally.  
Have fun...

#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	makefile
#	partyhlp
#	party.c
sed 's/^X//' << 'SHAR_EOF' > makefile
X# Run the install phase as root
X# The files target only needs to be hit once, the first time you build.
X
XCC=cc
XCFLAGS=-O -DUSG -s -o party  
XLCFLAGS=-68010
XINSTALL=/local/bin/
XPFILES=/usr/bbs/
X
Xparty:  party.c
X	$(CC) $(LCFLAGS) $(CFLAGS) party.c
X	chmod 755 party
X
Xinstall: party
X	ln $(INSTALL)party $(INSTALL)oparty
X	-rm $(INSTALL)party
X	mv ./party $(INSTALL)party
X	chmod 2711 $(INSTALL)party
X	chgrp party $(INSTALL)party
X
Xfiles:
X	echo > $(PFILES).party
X	echo > $(PFILES).party1
X	echo > $(PFILES).party2
X	echo > $(PFILES).party3
X	echo > $(PFILES).party4
X	echo > $(PFILES).party.passwd
X	echo > $(PFILES)potd
X	chmod 664 $(PFILES).party*
X	chmod 660 $(PFILES).party4 $(PFILES).party.passwd
X	echo "All files created, edit $(PFILES).party.passwd to set a password"
X
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > partyhlp
XThings typed in here are saved in a file.  Please
Xuse your common sense...
X
XPARTY help:
Xq	Exit the party program
X!	Unix shell escape
X%	Party Console
X		i = Invite a user to party
X		m = Send a one line message to user
X		n = Change name
X		p = Join a different party
X		r = Read file into party
X		s = Scroll back and read again
X		t = Toggle this message off/on
X		w = Who is on the system
X?	This message
Xh	This message
X(space) enter a response.
SHAR_EOF
sed 's/^X//' << 'SHAR_EOF' > party.c
X/*	John "C". Sucilla's party hack.
X *	This Party program is based on the single process party
X *	by Jan Wolter which was a rewrite of Marcus's PD party.
X *	Thanks for the original version(s) Jan and Marcus!
X *
X *      You should define either VER7 or USG to compile.
X *	I have no idea if it will still compile under Version 7 though...
X *	It works on my 3B1 (tarkus), a 3B2/300 (chinet) and an AT clown
X *	running Microport (igloo).
X *
X *      This program remains in the public domain because theres lots
X *	of Jan/Marcus code in it.
X **************************************************************************
X *	Hacks by John "C". Sucilla  ...ihnp4{chinet|nwutb}!jcs:
X *	Added "Party Console". Currently, the control center allows the user
X *	to:
X *
X *	1) Change his name (silently) in a party. A check is done to verify
X *	   that the requested new name does not exist in the passwd file.
X *	   Some people don't like their logname used in vain...
X *
X *	2) Switch from the standard party (/usr/bbs/.party) to one of 4
X *	   private parties (.party[1-4]). .party4 is accessed thru the
X *	   password in /usr/bbs/.party.passwd. It is not encrypted.
X *
X *	3) Read file capability added. Limited to 66 lines.
X *
X *	01/Aug/87 - jcs
X *	1) Added "who" command to console.
X *
X *	2) Added "invite" command to console. Echo to the invited user's
X * 	   tty if possible. If not possible, send mail. If they are not
X *	   logged in, abort.
X *
X *	31/Aug/87 - jcs
X *	1) Added support for the SHELL environment variable so Korn Shell
X *	   users can use thier alias's. If SHELL is not set, it uses /bin/sh.
X * 	2) Added a private message function. A one line message can be sent
X *	   to another user.
X *
X *	15/Feb/88 - jcs
X *	1) Added the scroll back function.
X *
X *	03/Jul/88 - jcs
X *	1) Added a "MOTD" type function.  Party will now print the contents
X *	   of /usr/bbs/potd if it exists.
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <fcntl.h>
X#include <signal.h>
X#include <setjmp.h>
X#include <pwd.h>
X#include <utmp.h>
X#ifdef VER7
X#include <sgtty.h>
X#endif
X#ifdef USG
X#include <termio.h>
X#include <ctype.h>
X#endif
X#ifdef EWOULDBLOCK
X#include <sys/file.h>   /* 4.2BSD flock */
X#endif
X
X#ifdef TCGETA
Xstruct termio cooked, cbreak;
X#define EOFCHAR (cooked.c_cc[VEOF])
X#define GTTY(fd, st)    ioctl(fd, TCGETA, (st))
X#define STTY(fd, st)    ioctl(fd, TCSETAF, (st))
X#endif
X
X#ifdef TIOCGETC
Xstruct tchars ctrlchars;
X#define EOFCHAR (ctrlchars.t_eofc)
Xstruct sgttyb cooked, cbreak;
X#define GTTY(fd, st)    ioctl(fd, TIOCGETP, (st))
X#define STTY(fd, st)    ioctl(fd, TIOCSETN, (st))
X#endif
X
X#ifdef LOCK_EX
X#define LOCK(file)      flock(fileno(file), LOCK_EX)
X#define UNLOCK(file)    flock(fileno(file), LOCK_UN)
X#else
X#define LOCK(file)      fseek(file, 0L, 0), chk_lock(file, 1, -1L)
X#define UNLOCK(file)    fseek(file, 0L, 0), chk_lock(file, 0, -1L)
X#endif
X
Xchar *passfile = "/usr/bbs/.party.passwd";
Xchar *partyfile = "/usr/bbs/.party";
Xchar *basename = "/usr/bbs/.";
Xchar *helpfile = "/usr/bbs/partyhlp";
Xchar *potdfile = "/usr/bbs/potd";
Xchar *name[20];
Xchar *VER = "Version 3.3.1";
Xchar id_alg;
Xchar *who_cmd = "who -T";
Xchar *invitation = "echo \"Party or Die!!!\" | mail ";
Xchar progname[14];
X
X#define ON 0
X#define OFF 1
Xint C_FLAG = ON;
X
XFILE *wfd;
Xint rst;
Xjmp_buf jenv;
Xextern int errno;
X
X#define BFSZ 200
Xchar inbuf[BFSZ+24];
X#define buf (inbuf+10)
Xchar *cancel = " XXX\n";
X
Xint alrm(), intr();
Xchar *getlogin(), *malloc(), *ctime(), *fgets(), *strchr();
Xstruct passwd *getpwnam(), *getpwuid();
Xlong lseek(), time();
X
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
Xregister int n, i;
Xchar ch, *pnl;
Xstruct passwd *pwd;
Xlong now = time((long *)0);
X
X        if (!(strcpy (name, getlogin())) || !(pwd = getpwnam(name))
X                || pwd->pw_uid != getuid()) {
X                if (pwd = getpwuid(getuid()))
X			strcpy (name, pwd->pw_name);
X                else
X			strcpy (name, "(unknown)");
X        }
X        strcpy(inbuf,name);
X        strcat(inbuf,":         ");
X
X        /* Get ioctl modes */
X        errno = 0;
X        GTTY(0,&cooked);
X#ifndef TCSETA
X        ioctl(0, TIOCGETC, &ctrlchars);
X#endif
X        if (errno != 0)
X        {
X                printf("Input not a tty");
X                exit(1);
X        }
X        cbreak = cooked;        /* This works? */
X#ifdef TCSETA
X        cbreak.c_lflag &= ~(ECHO | ICANON);
X        cbreak.c_cc[VMIN] = 1;
X        cbreak.c_cc[VTIME] = 0;
X#else   /* else use TIOCGETC v7 */
X        cbreak.sg_flags &= ~ECHO;
X        cbreak.sg_flags |= CBREAK;
X#endif
X
X	/* convert the program name to upper case */
X	for (i = 0; argv[0][i] != NULL; i++) {
X		progname[i] = toupper (argv[0][i]);
X	}
X	progname[++i] = NULL;
X
X        printf ("Welcome to %s  --  %s  Type ? for HELP, ", progname, VER);
X	printf ("%c for CONSOLE\n", 0x25);
X
X	/* Print the Party message of the day if it exists */
X	potd ();
X
X        /* Put up the signal handlers */
X        signal(SIGQUIT,intr);
X        signal(SIGINT,intr);
X        signal(SIGALRM,alrm);
X
X        /* Open partyfile and put in join message */
X        if ((wfd = fopen(partyfile,"a")) == NULL)
X        {
X                printf("Cannot write partyfile %s\n",partyfile);
X                exit(1);
X        }
X        LOCK(wfd);
X        fseek(wfd,0L,2);
X        fprintf(wfd,"---- %s joining (%.12s)\n",name,ctime(&now)+4);
X        fflush(wfd);
X        UNLOCK(wfd);
X
X        if ((rst = open(partyfile,O_RDONLY)) < 0)
X        {
X                printf("Cannot read partyfile %s\n",partyfile);
X                exit(1);
X        }
X
X        /* Position read pointer 300 characters from the end of the file */
X        if (lseek(rst,-300L,2) < 0)
X        {
X                /* File isn't that long -- start from begining */
X                lseek(rst,0L,0);
X        }
X        else
X                /* Skip forward to a newline */
X                while (read(rst,&ch,1) > 0 && ch != '\n')
X                        ;
X
X        /* Get in cbreak/noecho mode */
X        STTY(0,&cbreak);
X
X        for(;;)
X        {
X                if ((n = read(rst,buf,BFSZ)) > 0)
X                        write(1,buf,n);
X                else
X                {
X                        alarm(4);
X                        if (!setjmp(jenv))
X                        {
X                                read(0,&ch,1);
X                                
X                                alarm(0);
X                                if (ch == EOFCHAR) intr();
X				STTY(0,&cooked);
X                                switch (ch)
X                                {
X                                case '!':
X                                        putc('!',stderr);
X                                        if (fgets(buf,BFSZ,stdin))
X                                        {
X                                                if ((pnl = strchr(buf,'\n'))
X                                                    != NULL)
X                                                        *pnl = '\0';
X                                                usystem(buf);
X                                                fputs("!\n",stderr);
X                                        }
X                                        else
X                                                fputs(cancel,stderr);
X                                        STTY(0,&cbreak);
X                                        break;
X                                case 'q':
X                                        intr();
X                                        break;
X                                case '?':
X                                case 'h':
X                                        help();
X                                        break;
X				case '%':
X					control();
X					STTY(0, &cbreak);
X					break;
X                                default:
X					putc ('>', stderr);
X					putc (' ', stderr);
X					fputs (ch, stderr);
X                                        if (fgets(buf,BFSZ,stdin))
X                                        {
X                                                if (buf[0] != '\0')
X                                                {
X                                                        LOCK(wfd);
X                                                        fseek(wfd,0L,2);
X                                                        fputs(inbuf,wfd);
X                                                        fflush(wfd);
X                                                        UNLOCK(wfd);
X                                                }
X                                                else
X                                                        fputs(cancel,stderr);
X                                        }
X                                        else
X                                                fputs(cancel,stderr);
X                                        STTY(0,&cbreak);
X                                        break;
X                                }
X                        }
X                }
X        }
X}
X
Xalrm()
X{
X        signal(SIGALRM,alrm);
X        longjmp(jenv,1);
X}
X
Xintr()
X{
Xlong now = time((long *)0);
X
X        alarm(0);
X
X        signal(SIGINT,SIG_IGN);
X        signal(SIGQUIT,SIG_IGN);
X
X        LOCK(wfd);
X        fseek(wfd,0L,2);
X        fprintf(wfd,"---- %s leaving (%.12s)\n",name,ctime(&now)+4);
X        fflush(wfd);
X        UNLOCK(wfd);
X        printf("---- %s leaving (%.12s)\n",name,ctime(&now)+4);
X        STTY(0,&cooked);
X        exit(0);
X}
X
X
Xusystem(cmd)
Xchar *cmd;
X{
Xint cpid, wpid, status;
Xint (*old_intr)(), (*old_quit)();
Xchar *myshell[20];
X
X	if ((cpid = fork ()) == 0) {
X                setuid(getuid());
X                setgid(getgid());
X		strcpy (myshell, getenv ("SHELL"));
X		if (myshell[0] == NULL) {
X			strcpy (myshell, "/bin/sh");
X		}
X                execl(myshell,"sh","-c",cmd,(char *)0);
X                exit(-1);
X        }
X        old_intr = signal(SIGINT,SIG_IGN);
X        old_quit = signal(SIGQUIT,SIG_IGN);
X        while ((wpid = wait(&status)) != cpid && wpid != -1)
X                ;
X        signal(SIGINT,old_intr);
X        signal(SIGQUIT,old_quit);
X}
X
Xhelp()
X{
Xregister int hf;
Xregister int n;
X
X        if ((hf = open(helpfile,0)) < 0)
X                fprintf(stderr,"Cannot open help file %s\n",helpfile);
X        else
X        {
X                while((n = read(hf,buf,BFSZ)) > 0)
X                        write(1,buf,n);
X                close(hf);
X        }
X
X}
X
X
X#ifndef LOCK_EX
X/* Keep calling locking() until it works */
X
Xchk_lock(file,request,size)
XFILE *file;
Xint request;
Xlong size;
X{
X/* register int i = 5;
X *
X *        while (locking(fileno(file), request, size) && i--)
X *                sleep(1);
X */
X}
X#endif
X
X/*
X * This is the Party Console function.
X */
X
Xcontrol()
X{
Xint i, n, chelp;
Xchar nname[20];
Xchar myname[20];
Xstruct passwd *pwd;
X
X	if (C_FLAG == ON) {
X		printf("Party Console\n");
X		help_cntrl();
X	}
X	printf("\ncmd: ");
X
X	rewind(stdin);
X	chelp = getc(stdin);
X
X	switch (chelp) {
X	case 'n':
X		nname[0] = '\0';
X		printf ("Your new name: ");
X		rewind (stdin);
X                fgets (nname,80,stdin);
X		if (nname[0] != '\n') {
X
X			for (n = 1; n <= strlen(nname); n++) {
X				if (nname[n] == '\n') {
X					nname[n] = '\0';
X					break;
X				}
X			}
X
X			/*
X			 * Look for control or escapes in name, they can
X			 * can be used to look like a valid user.
X			 */
X
X			for (n = 0; n < (strlen(nname)); n++) {
X				if (nname[n] < 0x20 || nname[n] > 0x7e) {
X					printf("Illegal char in name\n");
X					return(1);
X				}
X			}
X
X		} else {
X			/* None given -- use real name */
X		}
X
X		/*
X		 * Test the requested name against valid users.
X		 * If a match is found, deny the change.
X		 */
X
X		pwd = getpwnam (nname);
X		strcpy (myname, getlogin ());
X
X		/*
X		 * Blow up if name exists in passwd file and is
X		 * not my name.
X		 */
X
X		if ((strcmp (nname, pwd->pw_name) == 0) &&
X		    (strcmp (myname, nname) != 0)) {
X			printf ("Sorry, name is reserved\n");
X			break;
X		}
X
X		if (strcmp (myname, nname) == 0) {
X			name[0] = NULL;
X			inbuf[0] = NULL;
X			strcpy (name,nname);
X			strcpy (inbuf,nname);
X			strcat (inbuf,":         ");
X			break;
X		} else {
X			name[0] = NULL;
X			inbuf[0] = NULL;
X			strcpy (name,nname);
X			strcpy (inbuf,nname);
X			strcat (inbuf,":         ");
X			break;
X		}
X	case 'h':
X	case '?':
X		fflush (stdin);
X		fflush (stdout);
X		fflush (stderr);
X		help_cntrl ();
X		break;
X	case 'p':
X		fflush (stdin);
X		fflush (stdout);
X		fflush (stderr);
X		private_party ();
X		break;
X	case 'r':
X		read_file ();
X		fflush (stdout);
X		fflush (stderr);
X		break;
X	case 'w':
X		who ();
X		break;
X	case 'i':
X		invite ();
X		break;
X	case 'm':
X		p_message();
X		break;
X	case 't':
X		fflush (stdin);
X		fflush (stdout);
X		fflush (wfd);
X		if (C_FLAG == ON)
X			C_FLAG = OFF;
X		else
X			C_FLAG = ON;
X		break;
X	case 's':
X		scrollback ();
X		break;
X	default:
X		printf ("Input error, returning to party...\n");
X		return;
X	}
X}
X
X/*
X * Help for Party Console.
X */
X
Xhelp_cntrl()
X{
X	printf ("i = Invite a user to party\n");
X	printf ("m = Send a one line message to user\n");
X	printf ("n = Change name\n");
X	printf ("p = Join a different party\n");
X	printf ("r = Read file into party\n");
X	printf ("s = Scroll back and read again\n");
X	printf ("t = Toggle this message off/on\n");
X	printf ("w = Who is on the system\n");
X}
X
X/*
X * This function will read a file into the party file.
X */
X
Xread_file()
X{
XFILE *rfile;
Xchar ifname[255];
Xchar fname[255];
Xchar fbuff[81];
Xint LIMIT = 66;		/* Limit is 66 limes */
Xint line_cnt = 0;
X
X	rewind (stdin);
X	printf ("File: ");
X	gets (ifname);
X	/* adjust */
X	strncpy (fname, ifname, (sizeof(ifname) -1));
X
X        if ((rfile = fopen (fname,"r")) == NULL) {
X                printf ("Can't open: %s\n",fname);
X                return;
X        }
X
X	fprintf (wfd,"\nFILE: %s entered by %s\n", fname, name);
X
X	while (fgets (fbuff,80,rfile) != NULL) {
X		line_cnt++;
X		if (line_cnt == LIMIT) {
X			printf ("Input file size exceeded...\n");
X			line_cnt = 0;
X			break;
X		} else {
X			fprintf (wfd,"%s", fbuff);
X		}
X	}
X
X	fflush (wfd);
X	fclose (rfile);
X
X}
X
X/*
X * This function will switch us out of the current party and into
X * a new one thru a call to align().
X */
X
Xprivate_party()
X{
Xint c;
Xchar new_table[8], pass[15];
Xchar p4pass[15];
XFILE *pfile;
X
X	printf("File to party in (0 (standard) or 1-4): ");
X	rewind(stdin);
X	c = getc(stdin);
X	fflush (stdin);
X	switch(c) {
X	case '0':
X		strcpy (new_table, "party");	/* Standard party file */
X		align(new_table);
X		break;
X	case '1':
X		strcpy (new_table, "party1");
X		align(new_table);
X		break;
X	case '2':
X		strcpy (new_table, "party2");
X		align(new_table);
X		break;
X	case '3':
X		strcpy (new_table, "party3");
X		align (new_table);
X		break;
X	case '4':
X		rewind (stdin);
X		strcpy (pass, getpass ("Password: "));
X		fflush (stdin);
X        	if ((pfile = fopen (passfile, "r")) == NULL) {
X                	printf ("Can't open: %s\n", passfile);
X			return;
X        	}
X		fgets (p4pass, 14, pfile);
X		fclose (pfile);
X		if (strncmp (pass, p4pass, (strlen (p4pass) -1)) == 0) {
X			strcpy (new_table, "party4");
X			align (new_table);
X		} else {
X			printf ("Attempt failed. Returning to party...\n");
X		}
X		break;
X	default:
X		printf("\nInput error, returning to old party...\n\n");
X		break;
X	}
X}
X
X/*
X * This function takes care of everything that needs to be modified for
X * a party file switch.
X */
X
Xalign(table)
Xchar *table;
X{
Xregister int n;
Xchar ch, *pnl;
Xchar *pfile[80];
Xstruct passwd *pwd;
Xlong now = time((long *)0);
X
X	name[0] = NULL;
X	inbuf[0] = NULL;
X	pfile[0] = NULL;
X	/* Set up path to the new party file */
X	strcpy (pfile, basename);
X	strcat (pfile, table);
X	/* Get user info */
X        if (!(strcpy (name, getlogin())) || !(pwd = getpwnam(name))
X            || pwd->pw_uid != getuid()) {
X                if (pwd = getpwuid(getuid()))
X			strcpy (name, pwd->pw_name);
X                else
X			strcpy (name, "(unknown)");
X        }
X        strcpy(inbuf,name);
X        strcat(inbuf,":         ");
X
X        fprintf(wfd,"---- %s has moved to %s\n", name, table);
X        fprintf(stderr,"\nEntering %s!\n\n", table);
X
X	/* close old partyfile */
X	fclose(wfd);
X
X        /* Open partyfile and put in join message */
X        if ((wfd = fopen(pfile,"a")) == NULL)
X        {
X                printf("Can't write partyfile %s\n",pfile);
X                exit(1);
X        }
X        fseek(wfd,0L,2);
X        fprintf(wfd,"---- %s joining (%s) (%.12s)\n",name,table,ctime(&now)+4);
X        fflush(wfd);
X
X        if ((rst = open(pfile,O_RDONLY)) < 0)
X        {
X                printf("Cannot read partyfile %s\n",pfile);
X                exit(1);
X        }
X
X        /* Position read pointer 300 characters from the end of the file */
X        if (lseek(rst,-300L,2) < 0) {
X                /* File isn't that long -- start from begining */
X                lseek(rst,0L,0);
X        } else
X                /* Skip forward to a newline */
X                while (read(rst,&ch,1) > 0 && ch != '\n') ;
X}
X
X/*
X * Display who is currently logged in
X */
X
Xwho()
X{
XFILE *pnt;
Xchar *in[81];
X
X	rewind (stdin);
X	if ((pnt = popen (who_cmd, "r")) == NULL) {
X		printf ("Can't get users, popen() failed.\n");
X		return;
X	}
X
X	while (fgets (in, 80, pnt) != NULL) {
X		printf ("%s", in);
X	}
X	pclose (pnt);
X}
X
X/*
X * Invite a user into party using a canned message
X */
X
Xinvite()
X{
XFILE *pnt;
XFILE *user_tty;
Xchar *User[20];
Xchar *message[100];
Xchar *write_buf[40];
Xchar *theirtty;
Xchar tmp[512];
Xstruct utmp *ptr, *user, *getutent();
Xvoid setutent();
Xint found;
X
X	found = 0;
X	rewind (stdin);
X	message[0] = NULL;
X	tmp[0] = NULL;
X	write_buf[0] = NULL;
X	User[0] = NULL;
X        printf ("User: ");
X        fgets (User, 19, stdin);
X
X	setutent();
X	while ((ptr = getutent()) != NULL)   {
X		if (strncmp(ptr->ut_user, User, (strlen (User) -1)) == 0)   {
X			user = ptr;
X			found = 1;
X			break;
X		}
X	}
X
X	if (!found)   {
X		printf ("User is not logged on\n");
X		return;
X	}
X
X	strcpy (tmp, "/dev/");
X	strcat (tmp, user->ut_line);
X	if ((user_tty = fopen (tmp, "w")) == NULL)   {
X		printf ("%s has disabled messages\n", user->ut_user);
X		/* Cant write, so mail it... */
X        	strcpy (message, invitation);
X        	strcat (message, User);
X		printf ("Sending mail to %s\n", user->ut_user);
X        	if ((pnt = popen (message, "r")) == NULL) {
X                	printf ("Can't invite user, popen() failed.\n");
X                	return;
X        	}
X        	pclose (pnt);
X	} else {
X		fclose (user_tty);
X		printf ("Inviting: /dev/%s  (%s)\n", user->ut_line,
X			 user->ut_user);
X		fflush (stdout);
X		strcpy (write_buf, "echo \"From ");
X		strcat (write_buf, name);
X		strcat (write_buf, ": Party or Die!!\"");
X		strcat (write_buf, "");
X		strcat (write_buf, " > /dev/");
X		strcat (write_buf, user->ut_line);
X		system (write_buf);
X		return;
X	}
X}
X 
X/*
X * Send a one line private message to another user.
X */
X
Xp_message()
X{
XFILE *user_tty;
Xchar *User[20];
Xchar *m_buff[80];
Xchar *write_buf[40];
Xchar tmp[512];
Xstruct utmp *ptr, *user, *getutent();
Xvoid setutent();
Xint found;
X
X	found = 0;
X	rewind (stdin);
X	tmp[0] = NULL;
X	write_buf[0] = NULL;
X	User[0] = NULL;
X        printf ("User: ");
X        fgets (User, 19, stdin);
X	rewind (stdin);
X
X	setutent();
X	while ((ptr = getutent()) != NULL)   {
X		if (strncmp(ptr->ut_user, User, (strlen (User) -1)) == 0)   {
X			user = ptr;
X			found = 1;
X			break;
X		}
X	}
X
X	if ( !found)   {
X		printf ("User is not logged on\n");
X		return (1);
X	}
X
X	printf ("Message: ");
X	fgets (m_buff, 79, stdin);
X	strcpy (tmp, "/dev/");
X	strcat (tmp, user->ut_line);
X	if ((user_tty = fopen (tmp, "w")) == NULL)   {
X		printf ("%s has disabled messages, aborted\n", user->ut_user);
X		return (1);
X	} else {
X		fclose (user_tty);
X		printf ("Message sent to: /dev/%s  (%s)\n", user->ut_line,
X			 user->ut_user);
X		strcpy (write_buf, "echo \"From ");
X		strcat (write_buf, name);
X		strcat (write_buf, ": ");
X		strcat (write_buf, m_buff);
X		strcat (write_buf, "\"");
X		strcat (write_buf, " > /dev/");
X		strcat (write_buf, user->ut_line);
X		fflush (stdout);
X		sleep (1);
X		system (write_buf);
X		return;
X	}
X}
X
Xscrollback ()
X{
Xint c, i, n, lines, orst, s_flg, q_flg;
Xchar *inp[6];
Xchar ch;
X
X	printf ("Number of lines to review: ");
X
X	rewind (stdin);
X	fgets (inp, 5, stdin);
X	c = atoi (inp);
X	fflush (stdin);
X	if (c == 0) c = 20;
X
X	/* Save previous location */
X	orst = rst;
X
X	/* Reverse seek c lines */
X	for ( i = 1; i <= c;) {
X        	if (lseek (rst, -1L, 1) < 0) {
X                	lseek (rst, 0L, 0);
X			break;
X        	}
X		if (read (rst, &ch, 1) > 0 && ch == '\n') {
X			i++;
X		}
X		lseek (rst, -1L, 1);
X	}
X
X	/* Seek forward to EOF and print each line */
X	i = q_flg = s_flg = 0;
X	while ((n = read (rst, buf, BFSZ)) > 0) {
X		i++;
X		if (i == 5) {
X			i = 0;
X			if (s_flg == 0) {
X				printf ("\nMore (q=quit, c=continuous): ");
X				c = getc (stdin);
X				switch (c) {
X				case 'q':
X					q_flg = 1;
X					break;
X				case 'c':
X					s_flg = 1;
X					break;
X				default:
X					break;
X				}
X				fflush (stdin);
X			}
X		}
X		if (q_flg == 1)
X			break;
X		else 
X			write (1, buf, n);
X	}
X	rst = orst;
X	lseek (rst, 0L, 2);
X	printf ("\n------------- review completed ------------\n");
X}
X
X/* This function prints the Party Message Of The Day */
Xpotd()
X{
XFILE *potdf;
Xchar *pbuf[81];
X
X	if ((potdf = fopen(potdfile, "r")) == NULL) {
X		return;
X	}
X
X	while ((fgets (pbuf, 80, potdf)) != NULL)
X		fputs (pbuf, stdout);
X
X	fclose (potdf);
X}
X
SHAR_EOF
exit

-- 
John "C". Sucilla,  A silicon based life form.
       {att,chinet,ddsw1}!tarkus!jcs
  You have a better idea? Now's the time..



More information about the Alt.sources mailing list