home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / TBZCDR11.ZIP / TBZCDRWY.C < prev    next >
C/C++ Source or Header  |  1995-06-25  |  10KB  |  414 lines

  1. /*
  2.    TBZCDRWY.C - A TriBBS-specific front door for the Z-Chat multinode, chat
  3.                 door, using TriDoor from Mark Goodwin.
  4.    Copyright (c) 1995 by Marc Brooks
  5.  
  6.    Compile as follows:
  7.  
  8.    Borland C++    : bcc -ml tbzcdrwy.c bctdoor.lib
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14. #include <time.h>
  15. #include <dos.h>
  16. #include <fcntl.h>
  17. #include <share.h>
  18. #include <sys\stat.h>
  19. #include <io.h>
  20.                  
  21. #include "tdoor.h"
  22. #include "triwho.h"
  23.  
  24. #define TRUE 1
  25. #define FALSE 0
  26.  
  27. #define DIM(x) (sizeof(x) / sizeof(x[0]))
  28.  
  29. #define MAX_NAME 30           /* determined by length of WHOSON data file */
  30. #define MAX_NODES 30          /* for this compilation */
  31. #define MAX_PATH 128
  32. #define MAX_LINE 80
  33. #define NOT_LOGGED_ON -1
  34.  
  35. #define TBZCVER "TriBBS Z-Chat Doorway 1.1"
  36.  
  37. const char *ChatStatStrings[] = {
  38.    "Available",
  39.    "NOT Available",
  40.     "Transfering a file",
  41.    "Entering a message",
  42.    "In another door",
  43.    "Group chatting",
  44.    "Waiting for node",
  45.     "Chatting with node"
  46. };
  47.  
  48. char common_path[MAX_PATH + 1];
  49. int maximum_nodes;
  50. int my_node;
  51.  
  52. struct {
  53.   char who[MAX_NAME + 1];
  54.   int where;
  55. } node_info[MAX_NODES];
  56.  
  57. typedef enum { INITIALIZE = 0,
  58.                     GET_NODE = 1,
  59.                     START_CHAT = 2,
  60.                     DIE = 3 } states;
  61.  
  62. states status;
  63.  
  64. typedef enum { READ_BINARY = 0, APPEND_TEXT = 1, READ_WRITE_BINARY = 2 } mode_flag;
  65. static int open_modes[] = { O_RDONLY | O_BINARY, O_WRONLY | O_APPEND | O_TEXT, O_RDWR | O_BINARY };
  66. static char* fopen_modes[] = { "rb", "at", "r+b" };
  67.                          
  68. static void GetOthers(void);
  69. static void GetConfigLine(FILE *cfg, int max, char *line, char *expected);
  70. static int GetNode(void);
  71. static int JustBack(void);
  72. static FILE *ReadWho(int node, TriWho *who);
  73. static void SetupStuff(char *cfg_file);
  74. static void TrimTail(char* str);
  75. static void EnterChat(int node);
  76. static FILE *ShareOpen(char* name, mode_flag open_mode, int share_mode);
  77.          
  78. extern unsigned _stklen = 8192;
  79.  
  80. int main(int ac, char *av[])
  81. {
  82.    if (ac < 2)
  83.    {
  84.       printf("%s\n", TBZCVER);
  85.       printf("Copyright (c) 1995, Phydeaux Software, Inc.\n\n");
  86.         printf("Thanks to: Mark Goodwin for TriDoor\n");
  87.         printf("You must supply a configuration file name.\n");
  88.       exit(1);
  89.     }
  90.    
  91.    TDInitialize(ac, av);
  92.    strcpy(TDDoorName, TBZCVER);
  93.    SetupStuff(av[1]);
  94.  
  95.    if (status != DIE)
  96.     {
  97.       if (!JustBack())
  98.       {
  99.          GetOthers();
  100.  
  101.          if (GetNode())
  102.          {
  103.             TDSetColor(WHITE, BLACK);
  104.                 TDPrintf("\nLoading the Z-Chat program.\n");
  105.                 return (0);
  106.          }
  107.         }
  108.    }
  109.  
  110.    TDSetColor(CYAN, BLACK);
  111.    TDPrintf("\nReturning you to the BBS.\n");
  112.  
  113.    sleep(1);
  114.     return (status == DIE ? 2 : 1);
  115. }
  116.  
  117. static void SetupStuff(char *cfg_file)
  118. {
  119.    FILE *cfg;
  120.    int i;
  121.    char line[MAX_LINE + 1];
  122.  
  123.     status = INITIALIZE;
  124.  
  125.     for (i = 0; i < MAX_NODES; i++)
  126.    {
  127.         node_info[i].who[0] = '\0';
  128.       node_info[i].where = NOT_LOGGED_ON;
  129.    }
  130.     
  131.     cfg = ShareOpen(cfg_file, READ_BINARY, SH_DENYNO);
  132.     if (cfg != NULL)
  133.     {
  134.       GetConfigLine(cfg, MAX_LINE, line, "BBS Type");     // get the bbs type
  135.       GetConfigLine(cfg, MAX_LINE, line, "Path to door file"); // skip the path to the door data files
  136.       GetConfigLine(cfg, MAX_LINE, line, "BBS Name");          // skip the bbs name
  137.       GetConfigLine(cfg, MAX_LINE, line, "Sysop Name");        // skip the sysop's name
  138.       GetConfigLine(cfg, MAX_LINE, line, "Locked baud rate");  // skip the locked baud rate
  139.       GetConfigLine(cfg, MAX_PATH, common_path, "Node one path"); // get the node one path
  140.       GetConfigLine(cfg, MAX_LINE, line, "Maximum nodes");     // get the maximum number of nodes
  141.         maximum_nodes = atoi(line);
  142.  
  143.         if ((maximum_nodes < 1) || (maximum_nodes > MAX_NODES))
  144.       {
  145.          status = DIE;
  146.          TDSetColor(RED, BLACK);
  147.          TDPrintf("HEY!  Maximum nodes must be between 1 and %d!\n\n", MAX_NODES);
  148.       }
  149.  
  150.         my_node = TDNode;
  151.       
  152.       if ((my_node < 1) || (my_node > maximum_nodes))
  153.       {
  154.          status = DIE;
  155.          TDSetColor(RED, BLACK);
  156.          TDPrintf("HEY!  The node number (%d) is invalid, must be 1 to %d (%d).\n\n", 
  157.                   my_node, maximum_nodes, MAX_NODES);
  158.       }
  159.         
  160.       fclose(cfg);
  161.     }
  162.    else {
  163.       status = DIE;
  164.       TDSetColor(RED, BLACK);
  165.       TDPrintf("HEY!  Can't find my configuration file (%s)!\n\n", cfg_file);
  166.    }
  167. }
  168.  
  169. static int JustBack(void)
  170. {
  171.     FILE *fp;
  172.     TriWho who;
  173.     int retval = 0;
  174.     
  175.     fp = ReadWho(my_node, &who);
  176.     if (fp != NULL)
  177.     {
  178.         if ((who.chat_status == TRI_IN_GROUP_CHAT) ||
  179.              (who.chat_status == TRI_WAITING_FOR_NODE) ||
  180.              (who.chat_status == TRI_IN_NODE_CHAT))
  181.         {
  182.             who.chat_status = TRI_IN_DOOR;
  183.             fseek(fp, 0L, SEEK_SET);
  184.             fwrite(&who, sizeof(who), 1, fp);
  185.             retval = 1;
  186.         }
  187.  
  188.         fclose(fp);
  189.     }
  190.  
  191.     return retval;
  192. }
  193.  
  194. static void GetOthers(void)
  195. {
  196.    FILE *fp;
  197.     int i;
  198.    TriWho who;
  199.    
  200.    for (i = 0; i < maximum_nodes; i++)
  201.    {
  202.       node_info[i].who[0] = '\0';
  203.       node_info[i].where = NOT_LOGGED_ON;
  204.  
  205.       fp = ReadWho(i + 1, &who);
  206.       if (fp != NULL)
  207.       {
  208.          strncpy(node_info[i].who, who.name, 31);
  209.          node_info[i].where = who.chat_status;
  210.  
  211.          fclose(fp);
  212.       }
  213.     }
  214. }
  215.  
  216. static int GetNode(void)
  217. {
  218.    int i;
  219.    char line[MAX_LINE];
  220.  
  221.    while (1)
  222.    {
  223.       TDSetColor(LIGHTGREEN, BLACK);
  224.       TDPuts("Node  Name");
  225.       for (i = 0; i < MAX_NAME - 4; i++)
  226.          TDPutch(' ');
  227.       TDPuts("  Chat Status\n");
  228.  
  229.       TDPuts("----  ");
  230.       for (i = 0; i < MAX_NAME; i++)
  231.             TDPutch('-');
  232.       TDPuts("  -------------------\n");
  233.  
  234.       for (i = 0; i < maximum_nodes; i++)
  235.       {
  236.          TDSetColor(LIGHTCYAN, BLACK);
  237.          TDPrintf(" %2d ", i + 1);
  238.  
  239.          if (node_info[i].where != NOT_LOGGED_ON)
  240.          {
  241.             TDSetColor(LIGHTGREEN, BLACK);
  242.             TDPrintf("  %-*.*s", MAX_NAME, MAX_NAME, node_info[i].who);
  243.             TDSetColor(WHITE, BLACK);
  244.             TDPrintf("  %s", (i + 1 == my_node) ?
  245.                              "Here!" :
  246.                              ChatStatStrings[node_info[i].where]);
  247.          }
  248.          else TDPuts("  No one logged into this node");
  249.           
  250.             TDPutch('\n');
  251.         }
  252.        
  253.       TDSetColor(LIGHTGREEN, BLACK);
  254.       TDPrintf("\nSelect Node number (1-%d), <G> for group chat, <ENTER> to quit: ",
  255.                maximum_nodes);
  256.       TDSetColor(WHITE, BLACK);
  257.       TDGets(line, MAX_LINE);
  258.  
  259.       if (line[0] == '\0')
  260.          return 0;
  261.  
  262.       if (toupper(line[0]) == 'G')
  263.       {
  264.          EnterChat(0);
  265.          return 1;
  266.       }
  267.  
  268.         i = atoi(line);
  269.  
  270.       if ((i < 1) && (i > maximum_nodes))
  271.         {
  272.          TDSetColor(BLACK, RED);
  273.          TDPrintf("\nYou must enter either a node number or G!\n");
  274.          continue;
  275.       }
  276.  
  277.       if (i == my_node)
  278.       {
  279.          TDSetColor(BLACK, RED);
  280.          TDPrintf("\nYou can't chat with yourself!\n");
  281.          continue;
  282.       }
  283.  
  284.       if (node_info[i - 1].where == TRI_UNAVAILABLE)
  285.         {
  286.             TDSetColor(BLACK, RED);
  287.             TDPrintf("\n%s does not want to chat right now!\n", node_info[i - 1].who);
  288.          continue;
  289.       }
  290.                           
  291.       if (node_info[i - 1].where == TRI_AVAILABLE)
  292.       {
  293.          TDSetColor(LIGHTCYAN, BLACK);
  294.             TDPrintf("\n%s will be notified you want to chat, be patient...\n",
  295.                   node_info[i - 1].who);
  296.       }
  297.  
  298.       EnterChat(i);
  299.       return 1;
  300.    }
  301. }
  302.  
  303. static void GetConfigLine(FILE *cfg, int max, char *line, char *expected)
  304. {
  305.     if (fgets(line, max, cfg) == NULL)
  306.    {
  307.       status = DIE;
  308.       TDSetColor(RED, BLACK);
  309.       TDPrintf("You seem to be missing something in the config file.\n");
  310.       TDPrintf("I was expecting %s, and the line was missing.\n", expected);
  311.    }                                                   
  312.     else TrimTail(line);
  313. }
  314.  
  315. static void TrimTail(char *str)
  316. {
  317.    register int i = strlen(str);
  318.    register char *end = &str[i - 1];
  319.    
  320.    while ((i > 0) && ((*end == '\n') || (*end == '\r') ||
  321.                              (*end == ' ') || (*end == '\t')))
  322.     {
  323.         i--;
  324.       *end-- = '\0';
  325.    }
  326. }
  327.  
  328. static void EnterChat(int node)
  329. {
  330.     FILE *fp;
  331.    int i;
  332.    TriWho who;
  333.    char who_file[MAX_PATH + 1];
  334.    
  335.    fp = ReadWho(my_node, &who);
  336.    if (fp != NULL)
  337.    {
  338.       if (node != 0)
  339.             who.chat_status = TRI_IN_NODE_CHAT;
  340.         else who.chat_status = TRI_IN_GROUP_CHAT;
  341.  
  342.         who.other_node = node;
  343.       fseek(fp, 0L, SEEK_SET);
  344.       fwrite(&who, sizeof(who), 1, fp);
  345.  
  346.       fclose(fp);
  347.    }
  348.  
  349.    /* If the node is 0 (which is group chat) then we send the message to */
  350.    /* all other nodes. */
  351.    for (i = 0; i < maximum_nodes; i++)
  352.    {
  353.       if (i + 1 == my_node)
  354.          continue;   /* don't tell me! */
  355.  
  356.         /* Don't nag that are not available for chat */
  357.         if (node_info[i].where != TRI_AVAILABLE)
  358.             continue;
  359.  
  360.       if ((node == i + 1) || (node == 0))
  361.       {
  362.             sprintf(who_file, "%s\\MWORK\\PAGE.%03d", common_path, i + 1);
  363.  
  364.             fp = ShareOpen(who_file, APPEND_TEXT, SH_DENYNO);
  365.             if (fp != NULL)
  366.             {
  367.                 fprintf(fp, "%s on node %d %s chat!\n",
  368.                           node_info[my_node - 1].who,
  369.                           my_node,
  370.                           node ? "wants to" : "just entered");
  371.                 fclose(fp);
  372.             }
  373.         }
  374.     }
  375. }
  376.  
  377. static FILE *ReadWho(int node, TriWho *who)
  378. {
  379.    FILE *fp;
  380.    char who_file[MAX_PATH + 1];
  381.    
  382.    sprintf(who_file, "%s\\MWORK\\WHOSON.%d", common_path, node);
  383.  
  384.     fp = ShareOpen(who_file, READ_WRITE_BINARY, SH_DENYNO);
  385.     if (fp != NULL)
  386.     {
  387.         if (fread(who, sizeof(*who), 1, fp) != 1)
  388.         {
  389.             fclose(fp);
  390.             fp = NULL;
  391.         }
  392.     }
  393.  
  394.     return fp;
  395. }
  396.  
  397. static FILE *ShareOpen(char* name, mode_flag open_mode, int share_mode)
  398. {
  399.     int fd;
  400.     FILE *fp = NULL;
  401.  
  402.     fd = sopen(name, open_modes[open_mode], share_mode, S_IREAD | S_IWRITE);
  403.  
  404.     if (fd != -1)
  405.     {
  406.         fp = fdopen(fd, fopen_modes[open_mode]);
  407.  
  408.         if (fp == NULL)
  409.             close(fd);
  410.     }
  411.          
  412.     return fp;
  413. }
  414.