home *** CD-ROM | disk | FTP | other *** search
- /*
-
- chat
- Written by D'Arcy J.M. Cain
- All rights reserved
-
- This is the front end to the chatter program. It is run by any number
- of users who wish to communicate conference style with each other. The
- chatter program serves each user.
-
- Permission is hereby granted to freely copy and redistribute this
- software, provided that the author is clearly credited in all
- copies and derivations. This software is provided ``As Is'' and
- without any express or implied warranties.
-
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <curses.h>
- #include <signal.h>
- #include <ctype.h>
- #include <errno.h>
- #include "chat.h"
-
- char chat_rcsid[] = "$Id: chat.c,v 1.2 90/10/26 19:55:16 darcy Exp Locker: darcy $\b ";
-
- extern char chc_rcsid[];
-
- #ifndef NO_CHG_NAME
- static char *options = "hn:f:";
- #else
- static char *options = "hf:";
- #endif
-
- extern int getopt(int argc, char **argv, const char *opts);
- extern int optind, opterr;
- extern char *optarg;
-
- extern int execlp(const char *path, const char *arg0, ...);
- extern int fork(void);
- extern int wait(int *stat_loc);
-
- static FILE *cap_file = NULL;
- static WINDOW *disp, *inp;
-
- #ifdef HALFDELAY_BROKEN
- int chat_suspended = 0;
- #endif
-
- void cleanup(int sig) /* come here on just about any signal */
- {
- while (chk_q()) /* clean up your own mess */
- ;
-
- if (cap_file != NULL)
- fclose(cap_file);
-
- chc_send("x");
-
- mvwprintw(inp, 1, 1, "%-77s", " So long... It's been nice chatting");
- wrefresh(disp); /* display any leftovers */
- wrefresh(inp); /* display polite message */
-
- delwin(disp);
- delwin(inp);
- endwin();
- ch_close();
- exit(0);
- }
-
- void disp_str(char *str) /* add latest string to list just above box */
- {
- scroll(disp); /* make room for it first */
- mvwprintw(disp, LINES - 5, 0, "%s", str);
-
- if (cap_file != NULL) /* save to file if it is open */
- fprintf(cap_file, "%s\n", str);
- }
-
- static int need_to_refresh = 0;
-
- int chk_q(void)
- {
- char msgbuf[256];
-
- if (ch_get(msgbuf))
- {
- disp_str(msgbuf); /*let user know what chatter has to say */
-
- if (*msgbuf == 'e') /* is chatter telling us to get lost? */
- {
- wrefresh(disp); /* display anything pending */
- cleanup(0); /* take the Big Sleep */
- }
-
- need_to_refresh = -1;
- return(1); /* let caller know */
- }
-
- return(0); /* nothing happened */
- }
-
- #ifndef NO_SH_ESC
- static void run_command(char *s)
- {
- int status, pid, w, tty;
- void (*istat)(), (*qstat)();
-
- if ((tty = open("/dev/tty", 2)) == -1)
- {
- fprintf(stderr, "Can't open /dev/tty\n");
- return;
- }
-
- if ((pid = fork()) == 0)
- {
- close(0); dup(tty);
- close(1); dup(tty);
- close(1); dup(tty);
- close(tty);
- execlp("sh", "sh", (*s ? "-c" : NULL), s, NULL);
- exit(0); /* note: We don't care about failure here */
- }
-
- close(tty);
- istat = signal(SIGINT, SIG_IGN);
- qstat = signal(SIGQUIT, SIG_IGN);
-
- while ((w = wait(&status)) != pid)
- if ((w == -1) && (errno != EINTR))
- break;
-
- signal(SIGINT, istat);
- signal(SIGQUIT, qstat);
- }
- #endif
-
- void help(void)
- {
- WINDOW *w;
- int k;
- static char *help_msg[] = {
- "CHAT - multi user conference utility",
- "Written by D'Arcy J.M. Cain (darcy@druid.uucp)",
- "Copyright 1990 - All rights reserved",
- "$Revision: 1.2 $\b " + 1,
- "",
- "chat commands consist of a slash (/) followed by a command",
- " ? this Help screen",
- #ifndef NO_SH_ESC
- " ! shell Escape",
- #endif
- " c Change channel i.e: \"/c3\" - change to channel 3",
- " Note: \"/c*\" will change to first empty channel",
- " h Same as ?",
- #ifndef NO_CHG_NAME
- " n change Name to following string",
- #endif
- " r Redraw screen",
- #ifndef NO_SHOW_USERS
- " s Show current users using chat",
- #endif
- " x eXit from chat",
- "",
- " Hit a key to continue ..."
- };
- #define HELP_SZ (sizeof(help_msg)/sizeof(char *))
-
- w = newwin(HELP_SZ + 3, 71, 1, 3); /* get a new window */
- box(w, 0, 0); /* and box it */
-
- for (k = 0; k < HELP_SZ; k++) /* display the help screen */
- mvwprintw(w, k + 1, 3, "%s", help_msg[k]);
-
- wrefresh(w); /* show the screen */
-
- while (wgetch(w) == ERR)
- ; /* wait for keystroke */
-
- delwin(w); /* clear the window */
- touchwin(disp); /* update display window */
- wrefresh(disp); /* get everything back in sync */
- wrefresh(inp);
- }
-
- int main(int argc, char **argv)
- {
- int c;
- char entry[512], *ptr = NULL, *ptr1, msgbuf[256];
-
- if ((ptr1 = ch_init()) != NULL)
- {
- perror(ptr1);
- return(1);
- }
-
- /* curses stuff */
- initscr();
- nonl();
- noecho();
- cbreak();
- #ifndef HALFDELAY_BROKEN
- halfdelay(20);
- #endif
-
- /* make sure we always exit through cleanup */
- signal(SIGINT, cleanup);
- signal(SIGABRT, cleanup);
- signal(SIGQUIT, cleanup);
- signal(SIGKILL, cleanup);
- signal(SIGTERM, cleanup);
-
- disp = newwin(LINES - 4, COLS, 0, 0); /* conversation window */
- idlok(disp, TRUE);
- scrollok(disp, TRUE);
-
- inp = newwin(3, COLS, LINES - 4, 0); /* input window */
- box(inp, 0, 0);
-
- mvwprintw(inp, 1, 1, "-> "); /* prompt string */
-
- while ((c = getopt(argc, argv, options)) != -1)
- {
- switch (c)
- {
- case '?':
- default:
- sprintf(entry, "%s: Invalid option %c", argv[0], c);
- disp_str(entry);
-
- case 'h':
- sprintf(entry,
- #ifndef NO_CHG_NAME
- "Usage: %s [-h] [-c channel] [-n name] [-f file]",
- #else
- "Usage: %s [-h] [-c channel] [-f file]",
- #endif
- argv[0]);
- disp_str(entry);
- cleanup(0);
- break;
-
- #ifndef NO_CHG_NAME
- case 'n':
- ptr = optarg;
- break;
- #endif
-
- case 'f':
- if ((cap_file = fopen(optarg, "a")) == NULL)
- {
- sprintf(entry, "Can't open log file: %s", sys_errlist[errno]);
- cleanup(0);
- }
- break;
- }
- }
-
- disp_str("chat - multi user conferencing utility"); /* signon string */
- disp_str("Written by D'Arcy J.M. Cain");
- disp_str("Copyright 1990 by D'Arcy J.M. Cain - All rights reserved");
- disp_str("$Revision: 1.2 $\b " + 1);
- disp_str("");
-
- /* open chat link */
- ch_init();
- sprintf(entry, "o%s", (ptr == NULL) ? cuserid(NULL) : ptr);
- chc_send(entry);
- sleep(1); /* messages are not FIFO */
-
- disp_str("Enter /h or /? for help");
- disp_str("");
- wrefresh(disp);
-
- ptr = entry;
- chc_send("s"); /* get list of current users */
-
- for (;;) /* loop till the cows come home */
- {
- while (chk_q())
- ;
-
- if (need_to_refresh)
- wrefresh(disp); /* refresh display if necessary*/
-
- wrefresh(inp); /* refresh this to place cursor */
-
- if ((c = wgetch(inp)) != ERR); /* if got a character (not timed out) */
- {
- if (c == 4)
- cleanup(0); /* end of session ? */
-
- if (c == '\r') /* end of line ? */
- {
- *ptr = 0;
-
- if (*entry == '/') /* command? */
- {
- switch (entry[1])
- {
- case 'v': /* file versions. undocumented */
- disp_str(chat_rcsid + 1);
- disp_str(chc_rcsid + 1);
- chc_send("v");
- break;
-
- case '?': /* request for help */
- case 'h':
- help();
- break;
-
- #ifndef NO_SH_ESC
- case '!': /* shell escape */
- ptr = entry + 2;
- while (isspace(*ptr))
- ptr++;
-
- #ifdef HALFDELAY_BROKEN
- chat_suspended = 1;
- #endif
- endwin();
- run_command(ptr);
- printf("\n[Press 'Enter' to continue ...]");
-
- while (gets(entry) == NULL)
- ;
-
- doupdate();
- #ifdef HALFDELAY_BROKEN
- chat_suspended = 0;
- #endif
- break;
- #endif
-
- case 'l': /* redraw screen */
- case 'r':
- clearok(disp, TRUE); /* update display window */
- clearok(inp, TRUE); /* update input window */
- wrefresh(disp); /* redraw both windows */
- wrefresh(inp);
- clearok(disp, FALSE); /* reset display window */
- clearok(inp, FALSE); /* reset input window */
- break;
-
- #ifndef NO_CHG_NAME
- case 'n': /* these are passed to chatter */
- #endif
- #ifndef NO_SHOW_USERS
- case 's':
- #endif
- case 'c':
- ptr = entry + 2;
- while (isspace(*ptr))
- ptr++;
- sprintf(msgbuf, "%c%s", entry[1], ptr);
- chc_send(msgbuf);
- break;
-
- case 'x': /* exit from chat */
- case 'q': /* for Dennis Breckenridge :-) */
- cleanup(0);
- break;
-
- default:
- beep();
- }
- }
- else if (*entry) /* else send it if not blank */
- {
- sprintf(msgbuf, "m%s", entry);
- chc_send(msgbuf);
- }
-
- ptr = entry; /* reset input box */
- mvwprintw(inp, 1, 1, "%77s", "");
- mvwprintw(inp, 1, 1, "-> ");
- }
- else if (c == '\b') /* take care of backspaces */
- {
- if (ptr != entry)
- {
- wprintw(inp, "\b \b");
- ptr--;
- }
- }
- else if (c == '\t') /* expand tabs */
- {
- ptr1 = ptr + 8 - ((ptr - entry) % 8);
- while (ptr != ptr1)
- {
- *(ptr++) = ' ';
- waddch(inp, ' ');
- }
- }
- else if ((c >= ' ') && (c < 0x7f)) /* otherwise if printable */
- {
- if ((ptr - entry) > 62) /* time for word wrap? */
- {
- *(ptr++) = c; /* don't lose latest char */
- *ptr = 0; /* terminate string */
-
- while (!isspace(*ptr)) /* find latest space */
- {
- if (--ptr == entry) /* special case - no spaces */
- {
- ptr += strlen(entry);
- *(ptr + 2) = 0;
- break;
- }
- }
-
- *(ptr++) = 0; /* change space to zero */
- sprintf(msgbuf, "m%s", entry);
- chc_send(msgbuf);
- strcpy(entry, ptr); /* change string to leftover */
- ptr = entry + strlen(entry);
- mvwprintw(inp, 1, 1, "%77s", ""); /* clear input box */
- mvwprintw(inp, 1, 1, "-> %s", entry); /* print string */
- }
- else
- waddch(inp, (*(ptr++) = c)); /* print character */
- }
- }
- }
- }
-