home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2002 / chat.c next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  9.3 KB  |  428 lines

  1.  /*
  2.  
  3. chat
  4. Written by D'Arcy J.M. Cain
  5. All rights reserved
  6.  
  7. This is the front end to the chatter program.  It is run by any number
  8. of users who wish to communicate conference style with each other.  The
  9. chatter program serves each user.
  10.  
  11. Permission is hereby granted to freely copy and redistribute this
  12. software, provided that the author is clearly credited in all
  13. copies and derivations.  This software is provided ``As Is'' and
  14. without any express or implied warranties.
  15.  
  16. */
  17.  
  18. #include    <stdio.h>
  19. #include    <stdlib.h>
  20. #include    <string.h>
  21. #include    <curses.h>
  22. #include    <signal.h>
  23. #include    <ctype.h>
  24. #include    <errno.h>
  25. #include    "chat.h"
  26.  
  27. char chat_rcsid[] = "$Id: chat.c,v 1.2 90/10/26 19:55:16 darcy Exp Locker: darcy $\b ";
  28.  
  29. extern char    chc_rcsid[];
  30.  
  31. #ifndef    NO_CHG_NAME
  32. static char    *options = "hn:f:";
  33. #else
  34. static char    *options = "hf:";
  35. #endif
  36.  
  37. extern int        getopt(int argc, char **argv, const char *opts);
  38. extern int        optind, opterr;
  39. extern char        *optarg;
  40.  
  41. extern int        execlp(const char *path, const char *arg0, ...);
  42. extern int        fork(void);
  43. extern int        wait(int *stat_loc);
  44.  
  45. static FILE        *cap_file = NULL;
  46. static WINDOW    *disp, *inp;
  47.  
  48. #ifdef    HALFDELAY_BROKEN
  49. int        chat_suspended = 0;
  50. #endif
  51.  
  52. void    cleanup(int sig)            /* come here on just about any signal */
  53. {
  54.     while (chk_q())                    /* clean up your own mess */
  55.         ;
  56.  
  57.     if (cap_file != NULL)
  58.         fclose(cap_file);
  59.  
  60.     chc_send("x");
  61.  
  62.     mvwprintw(inp, 1, 1, "%-77s", "    So long...   It's been nice chatting");
  63.     wrefresh(disp);                    /* display any leftovers */
  64.     wrefresh(inp);                    /* display polite message */
  65.  
  66.     delwin(disp);
  67.     delwin(inp);
  68.     endwin();
  69.     ch_close();
  70.     exit(0);
  71. }
  72.  
  73. void    disp_str(char *str)    /* add latest string to list just above box */
  74. {
  75.     scroll(disp);                /* make room for it first */
  76.     mvwprintw(disp, LINES - 5, 0, "%s", str);
  77.  
  78.     if (cap_file != NULL)        /* save to file if it is open */
  79.         fprintf(cap_file, "%s\n", str);
  80. }
  81.  
  82. static int    need_to_refresh = 0;
  83.  
  84. int        chk_q(void)
  85. {
  86.     char    msgbuf[256];
  87.  
  88.     if (ch_get(msgbuf))
  89.     {
  90.         disp_str(msgbuf);            /*let user know what chatter has to say */
  91.  
  92.         if (*msgbuf == 'e')            /* is chatter telling us to get lost? */
  93.         {
  94.             wrefresh(disp);            /* display anything pending */
  95.             cleanup(0);                /* take the Big Sleep */
  96.         }
  97.  
  98.         need_to_refresh = -1;
  99.         return(1);                    /* let caller know */
  100.     }
  101.  
  102.     return(0);                        /* nothing happened */
  103. }
  104.  
  105. #ifndef    NO_SH_ESC
  106. static void    run_command(char *s)
  107. {
  108.     int        status, pid, w, tty;
  109.     void    (*istat)(), (*qstat)();
  110.  
  111.     if ((tty = open("/dev/tty", 2)) == -1)
  112.     {
  113.         fprintf(stderr, "Can't open /dev/tty\n");
  114.         return;
  115.     }
  116.  
  117.     if ((pid = fork()) == 0)
  118.     {
  119.         close(0); dup(tty);
  120.         close(1); dup(tty);
  121.         close(1); dup(tty);
  122.         close(tty);
  123.         execlp("sh", "sh", (*s ? "-c" : NULL), s, NULL);
  124.         exit(0);        /* note:  We don't care about failure here */
  125.     }
  126.  
  127.     close(tty);
  128.     istat = signal(SIGINT, SIG_IGN);
  129.     qstat = signal(SIGQUIT, SIG_IGN);
  130.  
  131.     while ((w = wait(&status)) != pid)
  132.         if ((w == -1) && (errno != EINTR))
  133.             break;
  134.  
  135.     signal(SIGINT, istat);
  136.     signal(SIGQUIT, qstat);
  137. }
  138. #endif
  139.  
  140. void    help(void)
  141. {
  142.     WINDOW    *w;
  143.     int        k;
  144.     static char *help_msg[] = {
  145.         "CHAT - multi user conference utility",
  146.         "Written by D'Arcy J.M. Cain (darcy@druid.uucp)",
  147.         "Copyright 1990 - All rights reserved",
  148.         "$Revision: 1.2 $\b " + 1,
  149.         "",
  150.         "chat commands consist of a slash (/) followed by a command",
  151.         "   ?     this Help screen",
  152. #ifndef    NO_SH_ESC
  153.         "   !     shell Escape",
  154. #endif
  155.         "   c     Change channel i.e: \"/c3\" - change to channel 3",
  156.         "         Note: \"/c*\" will change to first empty channel",
  157.         "   h     Same as ?",
  158. #ifndef    NO_CHG_NAME
  159.         "   n     change Name to following string",
  160. #endif
  161.         "   r     Redraw screen",
  162. #ifndef    NO_SHOW_USERS
  163.         "   s     Show current users using chat",
  164. #endif
  165.         "   x     eXit from chat",
  166.         "",
  167.         "                       Hit a key to continue ..."
  168.     };
  169. #define    HELP_SZ    (sizeof(help_msg)/sizeof(char *))    
  170.  
  171.     w = newwin(HELP_SZ + 3, 71, 1, 3);    /* get a new window */
  172.     box(w, 0, 0);                        /* and box it */
  173.  
  174.     for (k = 0; k < HELP_SZ; k++)        /*  display the help screen */
  175.         mvwprintw(w, k + 1, 3, "%s", help_msg[k]);
  176.  
  177.     wrefresh(w);        /* show the screen */
  178.  
  179.     while (wgetch(w) == ERR)
  180.         ;                /* wait for keystroke */
  181.  
  182.     delwin(w);            /* clear the window */
  183.     touchwin(disp);        /* update display window */
  184.     wrefresh(disp);        /* get everything back in sync */
  185.     wrefresh(inp);
  186. }
  187.  
  188. int        main(int argc, char **argv)
  189. {
  190.     int        c;
  191.     char    entry[512], *ptr = NULL, *ptr1, msgbuf[256];
  192.  
  193.     if ((ptr1 = ch_init()) != NULL)
  194.     {
  195.         perror(ptr1);
  196.         return(1);
  197.     }
  198.  
  199.     /* curses stuff */
  200.     initscr();
  201.     nonl();
  202.     noecho();
  203.     cbreak();
  204. #ifndef    HALFDELAY_BROKEN
  205.     halfdelay(20);
  206. #endif
  207.  
  208.     /* make sure we always exit through cleanup */
  209.     signal(SIGINT, cleanup);
  210.     signal(SIGABRT, cleanup);
  211.     signal(SIGQUIT, cleanup);
  212.     signal(SIGKILL, cleanup);
  213.     signal(SIGTERM, cleanup);
  214.  
  215.     disp = newwin(LINES - 4, COLS, 0, 0);    /* conversation window */
  216.     idlok(disp, TRUE);
  217.     scrollok(disp, TRUE);
  218.  
  219.     inp = newwin(3, COLS, LINES - 4, 0);    /* input window */
  220.     box(inp, 0, 0);
  221.  
  222.     mvwprintw(inp, 1, 1, "-> ");            /* prompt string */
  223.  
  224.     while ((c = getopt(argc, argv, options)) != -1)
  225.     {
  226.         switch (c)
  227.         {
  228.             case '?':
  229.             default:
  230.                 sprintf(entry, "%s: Invalid option %c", argv[0], c);
  231.                 disp_str(entry);
  232.  
  233.             case 'h':
  234.                 sprintf(entry,
  235. #ifndef    NO_CHG_NAME
  236.                     "Usage: %s [-h] [-c channel] [-n name] [-f file]",
  237. #else
  238.                     "Usage: %s [-h] [-c channel] [-f file]",
  239. #endif
  240.                     argv[0]);
  241.                 disp_str(entry);
  242.                 cleanup(0);
  243.                 break;
  244.  
  245. #ifndef    NO_CHG_NAME
  246.             case 'n':
  247.                 ptr = optarg;
  248.                 break;
  249. #endif
  250.  
  251.             case 'f':
  252.                 if ((cap_file = fopen(optarg, "a")) == NULL)
  253.                 {
  254.                     sprintf(entry, "Can't open log file: %s", sys_errlist[errno]);
  255.                     cleanup(0);
  256.                 }
  257.                 break;
  258.         }
  259.     }
  260.     
  261.     disp_str("chat - multi user conferencing utility");    /* signon string */
  262.     disp_str("Written by D'Arcy J.M. Cain");
  263.     disp_str("Copyright 1990 by D'Arcy J.M. Cain - All rights reserved");
  264.     disp_str("$Revision: 1.2 $\b " + 1);
  265.     disp_str("");
  266.  
  267.     /* open chat link */
  268.     ch_init();
  269.     sprintf(entry, "o%s", (ptr == NULL) ? cuserid(NULL) : ptr);
  270.     chc_send(entry);
  271.     sleep(1);                                /* messages are not FIFO     */
  272.  
  273.     disp_str("Enter /h or /? for help");
  274.     disp_str("");
  275.     wrefresh(disp);
  276.  
  277.     ptr = entry;
  278.     chc_send("s");                            /* get list of current users */
  279.  
  280.     for (;;)                    /* loop till the cows come home */
  281.     {
  282.         while (chk_q())
  283.             ;
  284.  
  285.         if (need_to_refresh)
  286.             wrefresh(disp);        /* refresh display if necessary*/
  287.  
  288.         wrefresh(inp);            /* refresh this to place cursor */
  289.  
  290.         if ((c = wgetch(inp)) != ERR);    /* if got a character (not timed out) */
  291.         {
  292.             if (c == 4)
  293.                 cleanup(0);    /* end of session ? */
  294.  
  295.             if (c == '\r')    /* end of line ? */
  296.             {
  297.                 *ptr = 0;                    
  298.  
  299.                 if (*entry == '/')        /* command? */
  300.                 {
  301.                     switch (entry[1])
  302.                     {
  303.                         case 'v':        /* file versions.  undocumented */
  304.                             disp_str(chat_rcsid + 1);
  305.                             disp_str(chc_rcsid + 1);
  306.                             chc_send("v");
  307.                             break;
  308.  
  309.                         case '?':        /* request for help */
  310.                         case 'h':
  311.                             help();
  312.                             break;
  313.  
  314. #ifndef    NO_SH_ESC
  315.                         case '!':        /* shell escape */
  316.                             ptr = entry + 2;
  317.                             while (isspace(*ptr))
  318.                                 ptr++;
  319.  
  320. #ifdef    HALFDELAY_BROKEN
  321.                             chat_suspended = 1;
  322. #endif
  323.                             endwin();
  324.                             run_command(ptr);
  325.                             printf("\n[Press 'Enter' to continue ...]");
  326.  
  327.                             while (gets(entry) == NULL)
  328.                                 ;
  329.  
  330.                             doupdate();
  331. #ifdef    HALFDELAY_BROKEN
  332.                             chat_suspended = 0;
  333. #endif
  334.                             break;
  335. #endif
  336.  
  337.                         case 'l':        /* redraw screen */
  338.                         case 'r':
  339.                             clearok(disp, TRUE);    /* update display window */
  340.                             clearok(inp, TRUE);        /* update input window */
  341.                             wrefresh(disp);            /* redraw both windows */
  342.                             wrefresh(inp);
  343.                             clearok(disp, FALSE);    /* reset display window */
  344.                             clearok(inp, FALSE);    /* reset input window */
  345.                             break;
  346.  
  347. #ifndef    NO_CHG_NAME
  348.                         case 'n':        /* these are passed to chatter */
  349. #endif
  350. #ifndef    NO_SHOW_USERS
  351.                         case 's':
  352. #endif
  353.                         case 'c':
  354.                             ptr = entry + 2;
  355.                             while (isspace(*ptr))
  356.                                 ptr++;
  357.                             sprintf(msgbuf, "%c%s", entry[1], ptr);
  358.                             chc_send(msgbuf);
  359.                             break;
  360.  
  361.                         case 'x':        /* exit from chat */
  362.                         case 'q':        /* for Dennis Breckenridge :-) */
  363.                             cleanup(0);
  364.                             break;
  365.  
  366.                         default:
  367.                             beep();
  368.                     }
  369.                 }
  370.                 else if (*entry)        /* else send it if not blank */
  371.                 {
  372.                     sprintf(msgbuf, "m%s", entry);
  373.                     chc_send(msgbuf);
  374.                 }
  375.  
  376.                 ptr = entry;    /* reset input box */
  377.                 mvwprintw(inp, 1, 1, "%77s", "");
  378.                 mvwprintw(inp, 1, 1, "-> ");
  379.             }
  380.             else if (c == '\b')    /* take care of backspaces */
  381.             {
  382.                 if (ptr != entry)
  383.                 {
  384.                     wprintw(inp, "\b \b");
  385.                     ptr--;
  386.                 }
  387.             }
  388.             else if (c == '\t')    /* expand tabs */
  389.             {
  390.                 ptr1 = ptr + 8 - ((ptr - entry) % 8);
  391.                 while (ptr != ptr1)
  392.                 {
  393.                     *(ptr++) = ' ';
  394.                     waddch(inp, ' ');
  395.                 }
  396.             }
  397.             else if ((c >= ' ') && (c < 0x7f))    /* otherwise if printable */
  398.             {
  399.                 if ((ptr - entry) > 62)            /* time for word wrap? */
  400.                 {
  401.                     *(ptr++) = c;                /* don't lose latest char */
  402.                     *ptr = 0;                    /* terminate string */
  403.  
  404.                     while (!isspace(*ptr))        /* find latest space */
  405.                     {
  406.                         if (--ptr == entry)        /* special case - no spaces */
  407.                         {
  408.                             ptr += strlen(entry);
  409.                             *(ptr + 2) = 0;
  410.                             break;
  411.                         }
  412.                     }
  413.  
  414.                     *(ptr++) = 0;                /* change space to zero */
  415.                     sprintf(msgbuf, "m%s", entry);
  416.                     chc_send(msgbuf);
  417.                     strcpy(entry, ptr);            /* change string to leftover */
  418.                     ptr = entry + strlen(entry);
  419.                     mvwprintw(inp, 1, 1, "%77s", "");    /* clear input box */
  420.                     mvwprintw(inp, 1, 1, "-> %s", entry);    /* print string */
  421.                 }
  422.                 else
  423.                     waddch(inp, (*(ptr++) = c));        /* print character */
  424.             }
  425.         }
  426.     }
  427. }
  428.