rsalz@uunet.uu.net (Rich Salz) (09/13/88)
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@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@elgar.cts.com ARPA: elgar!ag@ucsd.edu -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.