v16i001: Multi-user conference system, Part01/05
Rich Salz
rsalz at uunet.uu.net
Tue Sep 13 06:05:27 AEST 1988
Submitted-by: Keith Gabryelski <ucsd!elgar!ag>
Posting-number: Volume 16, Issue 1
Archive-name: conf2/part01
Conf is a line oriented multi-user chat program designed to work on any
SysV, BSD, or Xenix system.
Conf has several advantages over the standard write program supplied
with most Unix and Xenix operating systems.
+ Unlimited users conferencing at once.
+ 100 separate discussion lines.
+ Public and private messages in addition to password
encrypted messages.
+ Quick and efficient user interaction.
+ User definable formats for messages.
+ Intelligent message display algorithm.
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# MANIFEST
# Makefile
# conf.c
# conf.el
export PATH; PATH=/bin:$PATH
if test -f 'MANIFEST'
then
echo shar: will not over-write existing file "'MANIFEST'"
else
cat << \SHAR_EOF > 'MANIFEST'
A Manifest Archived in
------------------------------------------------------------------------
MANIFEST 1
Makefile 1
conf.c 1
conf.el 1
conf.h 2
confalloc.c 2
config.h 2
confopts.c 2
confprnt.c 3
confrots.c 3
confrw.c 3
confsig.c 4
confstr.c 4
extern.h 4
structs.h 4
doc/READ_ME 5
doc/conf.1 5
doc/conf.txt 5
doc/confhelp 5
SHAR_EOF
fi # end of overwriting check
if test -f 'Makefile'
then
echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
SHELL=/bin/sh
INSTALL= mv
CFLAGS= -g
SRCS= conf.c confrw.c confrots.c confopts.c confalloc.c confstr.c confprnt.c confsig.c
OBJS= conf.o confrw.o confrots.o confopts.o confalloc.o confstr.o confprnt.o confsig.o
HEADERS= conf.h config.h extern.h structs.h
NEW= xconf
NAME= conf
LISP= conf.el
MAKES= Makefile
DOCDIR= doc
CONFLIB= /usr/lib/conf
CONFSPOOL= /usr/spool/conf
BINDIR= /usr/local/bin
LINT=lint
OWNER=conf
GROUP=conf
LIBS= -ltermlib
$(NEW): $(OBJS)
$(CC) $(CFLAGS) -o $(NEW) $(OBJS) $(LIBS)
all: $(NEW) install
clean:
rm -f *.o $(NEW) core
shar:
shar MANIFEST Makefile conf.c conf.el > confshar.1
shar conf.h confalloc.c config.h confopts.c > confshar.2
shar confprnt.c confrots.c confrw.c > confshar.3
shar confsig.c confstr.c extern.h structs.h > confshar.4
shar doc > confshar.5
lint:
$(LINT) $(LIBS) $(SRCS)
install:
cp $(NEW) $(BINDIR)/$(NAME)
-mkdir $(CONFLIB)
cp $(DOCDIR)/confhelp $(CONFLIB)
-chgrp $(GROUP) $(CONFLIB) $(CONFLIB)/confhelp $(BINDIR)/$(NAME)
-chown $(OWNER) $(CONFLIB) $(CONFLIB)/confhelp $(BINDIR)/$(NAME)
-chmod u+s $(BINDIR)/$(NAME)
-chmod 644 $(CONFLIB)/confhelp
-chmod 755 $(CONFLIB)
SHAR_EOF
fi # end of overwriting check
if test -f 'conf.c'
then
echo shar: will not over-write existing file "'conf.c'"
else
cat << \SHAR_EOF > 'conf.c'
#include "conf.h"
/* Talk, talk ... it's all talk! */
char *progname; /* program name (argv[0]) */
char *logname, *homedir;
int lfd, log_rfd, log_wfd, usr_fd;
long ourplace;
FILE *rec_fp;
int confing = FALSE;
char replyname[MAXNAMELEN] = "";
char replytty[MAXTTYLEN+1] = ""; /* there is a reason for the + 1
although I have forgotten it
right now, I'm sure it should
be there.
*/
char *wrdata;
unsigned wdlen=0;
struct cusrfil cuser, tuser;
struct clogfil clog, tlog;
#ifdef SYSV
struct termio term, saveterm;
#endif SYSV
#ifdef BSD
struct tchars chrstr;
struct sgttyb ktty;
int ttyflags;
#endif BSD
char ichar = CTRL('C'); /* interrupt character */
char qchar = CTRL('\\'); /* quit character */
jmp_buf env;
int columns = 80, lines = 24, banner = TRUE, seeme = TRUE, informe = FALSE,
lineinput = FALSE, beep = FALSE, expand8bit = TRUE, expandctrl = TRUE;
char *cls = NULL, *pager, *shell, *normform, *lineform, *shoutform, *sendform,
*informform, *recfile;
my_int()
{
longjmp(env, 1);
}
#ifdef BSD
stopit()
{
ktty.sg_flags = ttyflags;
stty(0, &ktty);
(void) signal(SIGTSTP, SIG_DFL);
(void) kill(0, SIGTSTP);
gtty(0, &ktty);
ttyflags = ktty.sg_flags;
if (!(ttyflags&ECHO))
lineinput = TRUE;
ktty.sg_flags |= CBREAK;
ktty.sg_flags &= ~ECHO;
stty(0, &ktty);
(void) ioctl(0, TIOCGETC, &chrstr);
ichar = chrstr.t_intrc;
qchar = chrstr.t_quitc;
(void) signal(SIGTSTP, stopit);
}
#endif BSD
main(argc, argv)
int argc;
char *argv[];
{
char *ptr, *word, *line, answer;
int num, x, c, old_umask, rotten_egg;
struct passwd *pt;
progname = *argv++; --argc;
/* Open all support files */
old_umask = umask(0);
x = 0;
while ((lfd = open(CONFLOCK, O_CREAT|O_EXCL, 0666)) < 0)
{
if (++x > 60) /* looks like the lock file may be hosed */
{
printf("The lock file %s looks like it is wedged.\n", CONFLOCK);
printf("What should I do; (A)bort, (C)ontinue, or (R)emove? ");
answer = 'a';
while (((c = getchar()) != '\n') && (c != CR))
{
switch(c)
{
case 'a':
case 'A':
case 'C':
case 'c':
case 'R':
case 'r':
answer = c;
break;
default:
printf("\n(A)bort, (C)ontinue, or (R)emove? ");
break;
}
}
switch(answer)
{
case 'a':
case 'A':
(void) umask(old_umask);
exit(-1);
case 'c':
case 'C':
x = 0;
continue;
case 'r':
case 'R':
(void) unlink(CONFLOCK);
continue;
}
sleep(1);
}
}
close(lfd);
if ((usr_fd = open(CONFUSERS, O_RDWR|O_CREAT, FILEMASK)) < 0)
{
(void) fprintf(stderr, "%s: couldn't open %s (%s)\n", progname,
CONFUSERS, puterr(errno));
(void) exit(-1);
}
(void) lseek(usr_fd, 0L, 0);
if ((argc == 1) && (!strcmp(*argv, "-T")))
{
(void) lseek(usr_fd, 0L, 0);
#ifdef SYSV
lockf(usr_fd, F_LOCK, 0L); /* lock user file */
#endif SYSV
#ifdef BSD
flock(usr_fd, LOCK_EX);
#endif BSD
rotten_egg = TRUE;
while (read(usr_fd, (char *)&tuser, sizeof(struct cusrfil)) ==
sizeof(struct cusrfil))
if (tuser.cu_flags != USER_OFF)
{
c = kill(tuser.cu_procid, 0);
if ((!c) || ((c < 0) && (errno != ESRCH)))
rotten_egg = FALSE;
}
#ifdef SYSV
(void) lseek(usr_fd, 0L, 0);
lockf(usr_fd, F_ULOCK, 0L);
#endif SYSV
#ifdef BSD
flock(usr_fd, LOCK_UN);
#endif BSD
if (rotten_egg)
{
close(usr_fd);
open(CONFLOG, O_TRUNC);
open(CONFUSERS, O_TRUNC);
}
unlink(CONFLOCK);
exit(0);
}
if ((log_wfd = open(CONFLOG, O_WRONLY|O_CREAT|O_APPEND, FILEMASK)) < 0)
{
(void) fprintf(stderr,"%s: couldn't create/open %s for writing(%s)\n",
progname, CONFLOG, puterr(errno));
(void) exit(-1);
}
(void) umask(old_umask);
if ((log_rfd = open(CONFLOG, O_RDONLY)) < 0)
{
(void) fprintf(stderr,"%s: couldn't open %s for reading (%s)\n",
progname, CONFLOG, puterr(errno));
(void) exit(-1);
}
unlink(CONFLOCK);
setuid(getuid());
(void) lseek(log_rfd, 0L, 2);
/* set up some pointers to interesting stuff */
wrdata = mymalloc(wdlen = PAGESIZ);
cuser.cu_line = 1;
cuser.cu_flags = USER_ON;
cuser.cu_procid = getpid();
pt = getpwuid(getuid());
if ((ptr = getlogin()) == NULL)
if ((ptr = pt->pw_name) == NULL)
ptr = "somebody"; /* can't figure this guy out */
logname = mymalloc((unsigned)(strlen(ptr)+1));
(void) strcpy(logname, ptr);
(void) strcpy(cuser.cu_cname, ptr);
if ((ptr = ttyname(0)) == NULL)
strcpy(cuser.cu_tty, "tty??");
else
strcpy(cuser.cu_tty, ((ptr= strrchr(ptr, '/')) ? ptr+1 : "tty??"));
homedir = mymalloc((unsigned)(strlen(pt->pw_dir)+1));
(void) strcpy(homedir, pt->pw_dir);
cls = mymalloc((unsigned)1);
*cls = '\0';
normform = mymalloc((unsigned)(sizeof(DEF_FORM_NORM)));
(void) strcpy(normform, DEF_FORM_NORM);
sendform = mymalloc((unsigned)(sizeof(DEF_FORM_SEND)));
(void) strcpy(sendform, DEF_FORM_SEND);
shoutform = mymalloc((unsigned)(sizeof(DEF_FORM_SHOUT)));
(void) strcpy(shoutform, DEF_FORM_SHOUT);
informform = mymalloc((unsigned)(sizeof(DEF_FORM_INFORM)));
(void) strcpy(informform, DEF_FORM_INFORM);
lineform = mymalloc((unsigned)(sizeof(DEF_FORM_LINE)));
(void) strcpy(lineform, DEF_FORM_LINE);
pager = mymalloc((unsigned)(sizeof(DEF_PAGER)));
(void) strcpy(pager, DEF_PAGER);
shell = mymalloc((unsigned)(sizeof(DEF_SHELL)));
(void) strcpy(shell, DEF_SHELL);
recfile = mymalloc((unsigned)(sizeof(DEF_RECFILE)));
(void) strcpy(recfile, DEF_RECFILE);
gettcap(); /* get termcap stuff */
getrc(); /* get some defaults from rc file */
getopts(); /* get some defaults from environment */
while (word = *argv++, argc--)
{
if (*word == '-')
{
word++;
while (*word != '\0')
{
switch(*word++)
{
case 'T':
printf("%s: -T wasn't specified by itself. Ignoring...\n",
progname);
case 'l':
if (*word == '\0')
{
if (!argc)
{
(void) printf("%s: -l switch specified without a conference line number\n",
progname);
usage();
}
word = *argv++; --argc;
}
num = atoi(word);
if ((num < 1) || (num > MAXCONFLINES))
{
(void) printf("%s: invalid conference line number: %d\n",
progname, num);
usage();
}
cuser.cu_line = num;
*word = '\0';
break;
case 's':
if (*word == '\0')
{
if (!argc)
{
(void) fprintf(stderr,
"%s: -s specified without a parameter\n",
progname);
usage();
}
word = *argv++; --argc;
}
if ((x = setopts(parsestr(word, strlen(word), NEXTWORD)))
!= FOUNDOPT)
{
char *errmess;
if (x == AMBIGUOUS)
errmess = "Ambiguous";
else
errmess = "Invalid";
(void) fprintf(stderr, "%s: %s -s parameter: %s\n",
progname, errmess, word);
usage();
}
*word = '\0';
break;
case 'w':
(void) do_who(0);
(void) exit(0);
default:
(void)fprintf(stderr, "%s: invalid parameter '%c'\n",
progname, *(word-1));
usage();
}
}
}
else
(void) do_ring(word);
}
/* by this point, all parameters/options have been parsed */
confing = TRUE;
clog.f_line = cuser.cu_line;
clog.f_usrlen = strlen(cuser.cu_cname) + 1;
clog.f_ttylen = strlen(cuser.cu_tty) + 1;
(void) lseek(usr_fd, 0L, 0);
#ifdef SYSV
lockf(usr_fd, F_LOCK, 0L); /* lock user file */
#endif SYSV
#ifdef BSD
flock(usr_fd, LOCK_EX);
#endif BSD
ourplace = lseek(usr_fd, 0L, 1);
while (read(usr_fd, (char *)&tuser, sizeof(struct cusrfil)) ==
sizeof(struct cusrfil))
if (tuser.cu_flags == USER_OFF)
break;
else
ourplace = lseek(usr_fd, 0L, 1);
(void) lseek(usr_fd, ourplace, 0);
write(usr_fd, (char *)&cuser, sizeof(struct cusrfil));
#ifdef SYSV
(void) lseek(usr_fd, 0L, 0);
lockf(usr_fd, F_ULOCK, 0L);
#endif SYSV
#ifdef BSD
flock(usr_fd, LOCK_UN);
#endif BSD
/* any fatal errors pass this point must do a nice_exit(status) */
write_log(INFORM, "Login", (char *)NULL, 0, (unsigned)strlen("Login"));
#ifdef SYSV
(void) ioctl(0, TCGETA, &term);
saveterm=term;
if (!(term.c_lflag&ECHO))
lineinput = TRUE;
ichar = term.c_cc[VINTR];
qchar = term.c_cc[VQUIT];
term.c_iflag &= ~(ICRNL);
term.c_lflag &= ~(ICANON|ECHO);
term.c_cc[VEOF] = 1;
term.c_cc[VEOL] = 0;
(void) ioctl(0, TCSETAW, &term);
#endif SYSV
#ifdef BSD
gtty(0, &ktty);
ttyflags = ktty.sg_flags;
if (!(ttyflags&ECHO))
lineinput = TRUE;
ktty.sg_flags |= CBREAK;
ktty.sg_flags &= ~ECHO;
stty(0, &ktty);
(void) ioctl(0, TIOCGETC, &chrstr);
ichar = chrstr.t_intrc;
qchar = chrstr.t_quitc;
#endif BSD
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, fatal);
(void) signal(SIGHUP, nice_exit);
(void) signal(SIGTERM, nice_exit);
(void) signal(SIGILL, fatal);
(void) signal(SIGTRAP, fatal);
(void) signal(SIGIOT, fatal);
(void) signal(SIGEMT, fatal);
(void) signal(SIGFPE, fatal);
(void) signal(SIGBUS, fatal);
(void) signal(SIGSEGV, fatal);
(void) signal(SIGSYS, fatal);
(void) signal(SIGPIPE, fatal);
#ifdef SIGTSTP
(void) signal(SIGTSTP, stopit);
#endif SIGTSTP
if (banner)
(void) version(FALSE);
(void) printf("login user %s (%s) on conference line %d\n",
cuser.cu_cname, cuser.cu_tty, cuser.cu_line);
if (setjmp(env))
{
(void) signal(SIGINT, my_int);
dispchar(ichar, stdout, NOVIS);
(void) putchar('\n');
(void) lseek(log_rfd, 0L, 2);
}
else
(void) signal(SIGINT, my_int);
forever
{
read_log();
fflush(stdout); /* damnit */
line = getline();
(void) signal(SIGINT, my_int);
if (line != NULL)
{
if ((*line == ':') && (*(line+1) != ':'))
{
if (*(line+1) == '!')
keep_shell(line+2);
else
{
--linelen;
(void) intpret(line+1);
}
}
else
{
if (*line == ':')
write_log(NORMAL, line+1, (char *)NULL, 0, linelen-1);
else
write_log(NORMAL, line, (char *)NULL, 0, linelen);
}
free(line);
}
}
}
nice_exit(status)
int status;
{
make_nice(TRUE);
(void) signal(SIGALRM, SIG_DFL);
(void) signal(SIGINT, SIG_DFL);
(void) signal(SIGQUIT, SIG_DFL);
(void) signal(SIGHUP, SIG_DFL);
(void) signal(SIGTERM, SIG_DFL);
(void) signal(SIGILL, SIG_DFL);
(void) signal(SIGTRAP, SIG_DFL);
(void) signal(SIGIOT, SIG_DFL);
(void) signal(SIGEMT, SIG_DFL);
(void) signal(SIGFPE, SIG_DFL);
(void) signal(SIGBUS, SIG_DFL);
(void) signal(SIGSEGV, SIG_DFL);
(void) signal(SIGSYS, SIG_DFL);
(void) signal(SIGPIPE, SIG_DFL);
(void) exit(status);
}
make_nice(status)
int status;
{
(void) alarm(0);
if (status)
write_log(INFORM,"Logout",(char *)NULL,0, (unsigned)strlen("Logout"));
if (cuser.cu_flags&USER_RECORD)
(void)fclose(rec_fp);
cuser.cu_flags = USER_OFF;
write_usr();
(void) close(usr_fd);
(void) close(log_rfd);
(void) close(log_wfd);
#ifdef SYSV
(void) ioctl(0, TCSETAW, &saveterm);
#endif SYSV
#ifdef BSD
ktty.sg_flags = ttyflags;
stty(0, &ktty);
#endif BSD
execlp(progname, progname, "-T", (char *)0);
}
usage()
{
(void) fprintf(stderr,
"usage: %s [-T][-w][-s switchname][-l line-number]\n",
progname);
(void) exit(-1);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'conf.el'
then
echo shar: will not over-write existing file "'conf.el'"
else
cat << \SHAR_EOF > 'conf.el'
;; Run conf(1) as asynchronous inferior of Emacs.
;; provided by Michael Ditto (ford at kenobi.cts.com)
;; This file is not part of GNU Emacs.
(defvar conf-process nil "The process of conf.")
(defun conference (switches)
"Conference with other users."
(interactive "sArgs to conference (switches): ")
(require 'shell)
(let ((buffer (get-buffer-create "*conference*")))
(switch-to-buffer buffer)
(if (get-buffer-process buffer)
(error "A conference process is already running"))
(setq conf-process
(start-process "conf" buffer
"/bin/sh" "-c" (format "conf %s" switches))))
(shell-mode)
(turn-on-auto-fill)
(setq mode-name "Conference")
(set-marker (process-mark conf-process) (point-max))
(set-process-filter conf-process 'conf-filter))
(defun conf-filter (process string)
(save-excursion
(set-buffer (process-buffer process))
(goto-char (process-mark process))
(let ((start-line (point)))
(insert-before-markers string)
;; (fill-region start-line (point))
)
(if (get-buffer-window (process-buffer process))
nil
(beep t))))
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
--
"If green is all there is to be, then green is good enough for me" - ktf
[ Keith ] UUCP: {ucsd, cbosgd!crash, sdcsvax!crash, nosc!crash}!elgar!ag
[Gabryelski] INET: ag at elgar.cts.com ARPA: elgar!ag at ucsd.edu
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
More information about the Comp.sources.unix
mailing list