home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 11 / 11.iso / n / n002 / 4.ddi / DEMOS.ZIP / BBS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-16  |  44.3 KB  |  1,441 lines

  1. /*
  2.     BBS.C - Bulletin board system
  3.  
  4.     You are free to use this program as you see fit, with or
  5.     without the copyright notices.
  6.  
  7.     Revisions :
  8.     JHL 12-90 : eliminated all warnings with forward function declarations.
  9.     JHL 01-91 : After connecting over modem, pause 2 seconds for line
  10.                to stabilize.
  11.  
  12.     (C) Copyright 1986, 1987, 1988, 1989, 1991 South Mountain Software, Inc. 
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17.  
  18. #include "eclproto.h"
  19. #include "im.h"     /* Intelligent modem */
  20. #include "xm.h"     /* XMODEM */
  21. #include "xc.h"     /* Communications services */
  22. #include "i86.h"
  23.  
  24. /* Forward declarations of static functions */
  25. static int intro(void);
  26. static char *logit(char *string);
  27. static int is_dead(void);
  28. static int is_break(void);
  29. static int passwd(char *prompt);
  30. static int add(char *password);
  31. static int search(char *pwd,char *name);
  32. static int online(void);
  33. static int download(void);
  34. static int upload(void);
  35. static int files(int display);
  36. static int typefile(void);
  37. static int send_msg(int display,int inputd);
  38. static int read_msg(int display,int inputd);
  39. static int chat(void);
  40. static int leave(int reason);
  41. static int idle(void);
  42. static int echoln(char *string,int option);
  43. static int echo(char ch,int  option);
  44. static int getinput(char *buffer,int option);
  45. static int main_menu(void);
  46. static int options(void);
  47. static int window(int row,int row_count,int column,char attribute,int flag);
  48. static void sclear(void);
  49. static void wclear(void);
  50. static int dfield(int index);
  51. static char *int2asc(int ivalue);
  52. static char *tod(void);
  53. static int modem_type = 0;
  54.  
  55.  
  56.  
  57. /*  Keyboard definitions   */
  58.  
  59. #define FK1         0x3B00          /* Function key 1 */
  60. #define FK2         0x3C00          /* Function key 2 */
  61. #define FK3         0x3D00          /* Function key 3 */
  62. #define FK4         0x3E00          /* Function key 4 */
  63. #define FK5         0x3F00          /* Function key 5 */
  64. #define RUB1        0x08            /* Rubout */
  65. #define RUB2        0x7F            /* Rubout */
  66. #define RET         0x0D            /* CR */
  67.  
  68. #define RINGS       5               /* Number of rings to answer on */
  69. #define CTRL_Z      0x1A            /* EOFILE */
  70. #define XON         0x11            /* Enable data transmission */
  71. #define XOFF        0x13            /* Disable data transmission */
  72.  
  73. /*  Miscellaneous  */
  74.  
  75. #define RETRIES      3              /* Signon retries */
  76. #define MIN_BUFFERS  8              /* Minimum buffers required */
  77. #define SCROLL       1              /* Scroll flag value */
  78. #define CLEARS       0              /* Clear the screen value */
  79. #define MAXFIELD    79              /* Maximum field */
  80. #define STATUSROW   24              /* Row address of status row */
  81. #define SCRWIDTH    79              /* Last column */
  82. #define STATCOLUMN  31              /* Starting column of rightmost status */
  83. #define STATWIDTH   48              /* Width of the rightmost status */
  84.  
  85. #define LOG_INTRO   0                   /* logs[...] */
  86. #define LOG_EXIT    1
  87. #define LOG_SON     2
  88. #define LOG_NEW     3
  89. #define LOG_OLD     4
  90. #define LOG_OFF     5
  91. #define LOG_TERM    6
  92. #define LOG_PASS    7
  93. #define LOG_CONN    8
  94. #define LOG_RING    9
  95. #define LOG_TIMO    10
  96.  
  97. #define XMODEM      11
  98. #define SESSION     12
  99. #define FAILED      13
  100. #define CANCELLD    14
  101. #define USERABORT   15
  102. #define FILEOPEN    16
  103. #define FILEIO      17
  104.  
  105. static char *logs[] = {
  106.     "*** BBS Started",                  /* LOG_INTRO */
  107.     "*** BBS Exited",                   /* LOG_EXIT */
  108.     "Answered at ",                     /* LOG_SON */
  109.     " new user on ",                    /* LOG_NEW */
  110.     " old user on ",                    /* LOG_OLD */
  111.     " logged off",                      /* LOG_OFF */
  112.     " aborted by BBS - shutdown ",      /* LOG_TERM */
  113.     " aborted by BBS - bad password ",  /* LOG_PASS */
  114.     " User lost connection ",           /* LOG_CONN */
  115.     " RING acknowledged by BBS ",       /* LOG_RING */
  116.     " User timeout ",                   /* LOG_TIMO */
  117.  
  118.     "Transfer completed",
  119.     "Transfer session error",
  120.     "Transfer failed",
  121.     "Transfer cancelled by user",
  122.     "Transfer was terminated by BBS",
  123.     "Transfer file open error",
  124.     "Transfer file I/O error",
  125.  
  126.     ""
  127. };
  128.  
  129. static char    logbuf[80];
  130. static char    Username[40];
  131. static char    bbs[] = "BBS";
  132.  
  133. static char xmodeminfo[] =
  134.   "Blocks transferred [%d]  refused [%d]  timeouts [%d]  garbled [%d]";
  135. /*  File names used by BBS  */
  136. static char    log_file[] = "LOG.ASC";
  137. static char    int_file[] = "INTRO.ASC";
  138. static char    msg_file[] = "MESSAGE.ASC";
  139. static char    msg_temp[] = "MESSAGE.$$$";
  140. static char    pas_file[] = "PASSWORD.ASC";
  141. static char    dir_file[] = "FILES.ASC";
  142.  
  143. static char    product[]  =  "\n\nSouth Mountain Bulletin Board System Rev. 4.0\n";
  144. static char    copyr1[]   =  "Copyright (C) 1991 South Mountain Software, Inc.\n";
  145.  
  146. /*  Field indices (into the <text> array structure) */
  147.  
  148. #define MAIN_F1     0
  149. #define MAIN_EXIT   1
  150. #define MAIN_STAT   2
  151. #define OPTN_F1     3
  152. #define OPTN_F2     4
  153. #define OPTN_F3     5
  154. #define OPTN_F4     6
  155. #define OPTN_EXIT   7
  156.  
  157. #define NULL_STR    8                   /* The last one */
  158.  
  159. #define COMPORT     28
  160. #define COMBAUD     30
  161. #define COMPARITY   38
  162. #define COMDATA     41
  163. #define COMSTOP     43
  164.  
  165. #define COM_HELP    45
  166. #define COM_ACCEPT  46
  167. #define COM_ABORT   47
  168. #define COM_ACP     48
  169.  
  170.  
  171. static struct {
  172.     int row;                            /* Row coordinate */
  173.     int col;                            /* Column coordinate */
  174.     int wid;                            /* Width */
  175.     char *str;                          /* Character string */
  176. } text[] = {
  177.     { STATUSROW, 18, 12, "[F1] options" },
  178.     { STATUSROW,  0, 17, "[Ctrl-Break] Exit" },
  179.     { STATUSROW, STATCOLUMN, STATWIDTH, logbuf },
  180.  
  181.     { STATUSROW,  0, 14, "[F1] Send mail" },
  182.     { STATUSROW, 15, 14, "[F2] Read mail" },
  183.     { STATUSROW, 30, 13, "[F3] File dir" },
  184.     { STATUSROW, 44, 14, "[F4] File load" },
  185.     { STATUSROW, 59, 17, "[Ctrl-Break] Exit" },
  186.  
  187.     { STATUSROW,  0, SCRWIDTH, "" },
  188.     { 0, 0, 0, "" }
  189. };
  190.  
  191. static char *baudstr[] = {
  192.     "110 baud", "150 baud", "300 baud", "600 baud", 
  193.     "1200 baud", "2400 baud", "4800 baud", "9600 baud",
  194.      "19200 baud", "38400 baud","57K baud","115K baud"
  195. };
  196.  
  197. static char Firstname[] = "\nEnter your name : ";
  198. static char Nouser[]    = "\n\007There is no user with that name\n";
  199. static char Password[]  = "\nWelcome back! Please enter your password : ";
  200. static char Hellonew[]  = "\nA new USER! - create a password : ";
  201. static char Logoff[]    = "\nThe BBS is coming down - NOW!\n";
  202. static char NoResponse[]= "\nYou haven't typed anything in 2 minutes - BYE!\n";
  203. static char Oops[]      = "\007 Please enter a valid command letter\n";
  204. static char Illpass[]   = "\nPassword is not legal\n";
  205. static char Thanks[]    = "\nThank you very much\n";
  206. static char Chat1[]     = "\nEnter characters (press Ctrl-Z to exit):\n";
  207. static char Nofile[]    = "\n\007No files are available for download\n";
  208. static char Whatfile[]  = "\nWhat file do you wish to view : ";
  209. static char Upfile[]    = "\nWhat file do you wish to upload : ";
  210. static char Downfile[]  = "\nWhat file do you wish to download : ";
  211. static char Towhom[]    = "\nSend message to (give user name or 'BBS') : ";
  212. static char Nofilex[]   = "\n\007The file you requested does not exist\n";
  213. static char Textend[]   = "\n[Thank you]\n";
  214. static char No_msg[]    = "\n\007You have no messages\n";
  215. static char Msgwhen[]   = "[Message dated] ";
  216. static char Msgfrom[]   = "\n[From] ";
  217. static char Msgstart[]  = "\n";
  218. static char Msgend[]    = "\n";
  219. static char Delmsg[]    = "\nDo you wish to delete the message (Y or N) : ";
  220. static char Byebye[]    = "\nBye bye - please disconnect your modem\n";
  221. static char Filereq[]   = "\nEnter the filename you wish to load into BBS : ";
  222. static char Descrip[]   = "\nEnter in a brief description : ";
  223. static char Opt_inst[]  = "\nPress one of the function keys below\n\n";
  224. static char Getready[]  = "\nNow, start your PC file transfer\n";
  225. static char NoModem[]   = "\nYour modem is not working!\n";
  226. static char *Menu[] = {
  227.     "\n\nCommand Choices are:\n\n",
  228.     "R  Read messages\n",
  229.     "S  Send messages\n",
  230.     "C  Chat with the BBS\n",
  231.     "U  Upload a file\n",
  232.     "D  Download a file\n",
  233.     "F  File directory list\n",
  234.     "V  View a text file\n",
  235.     "Q  Quit\n",
  236.     "\nEnter command desired : ",
  237.     ""
  238. };
  239.  
  240.  
  241. #define INPT_COM    64                      /* User keyboard entry */
  242. #define INPT_KEY    32                      /* BBS keyboard entry */
  243. #define INPT_UPR    16                      /* Uppercase conversion */
  244. #define ECHO_SCR    8                       /* Send to the screen */
  245. #define ECHO_COM    4                       /* Send to the comm port */
  246. #define ECHO_DOT    1                       /* Display a dot */
  247.  
  248. /*  User or BBS abort status */
  249.  
  250. #define BBS_OK      0                       /* abort_status */
  251. #define BBS_TERM    1                       /* BBS wants to terminate user */
  252. #define USER_DISC   2                       /* User dropped CD */
  253. #define USER_TIMO   3                       /* No response */
  254.  
  255. static int abort_status    = BBS_OK;
  256.  
  257.  
  258. /*  Modem session status */
  259.  
  260. #define COMM_IDLE   0           
  261. #define COMM_CONN   1
  262.  
  263. static int comm_status     = COMM_IDLE;
  264. static int bbs_noecho = 0;                  /* Enable bbs_noecho */
  265. static int bbs_hardwire = 0;                     /* linked via null modem if = 1 */
  266.                                              /* or 2nd command line arg = 'H' */
  267.  
  268. #define TIMEOUT 1500
  269. static int timeoutf = 0;                   /* Flag if set means waiting for input */
  270.  
  271.  
  272. /*  COMMUNICATIONS CONFIGURATION -- ALWAYS COM1!  */
  273.  
  274. #define DEFBAUD BAUD1200
  275. static int Port = COM1;                    /* Default communications port */
  276. static int Baud = DEFBAUD;                 /* Default baud rate */
  277. static int Parity = NOPAR;                 /* Default parity */
  278. static int Data = DATA8;                   /* Default data bit size */
  279. static int Stop = STOP1;                   /* Default stop bit */
  280. static int attr_status = 0x70;             /* Default attribute */
  281. static int attr_text   = 0x07;             /* Text window (emulator) attribute */
  282.  
  283. static char *days[] = {
  284.     "Sun ", "Mon ", "Tue ", "Wed ", "Thu ", "Fri ", "Sat "
  285. };
  286.  
  287. static char    buffer[26];            /* Working character buffer */
  288. static  union i86_reg packet;  /* DOS interrupt request handler */
  289.  
  290. static char intbuffer[3];      /* Convert an 8-bit integer to ASCII-decimal */
  291.  
  292.  
  293. void main(
  294. int argc,
  295. char *argv[])
  296. {
  297.     int     i, idx;
  298.  
  299.     if (argc == 3) {
  300.         switch (*argv[1]) {
  301.         case '1':       /* Assume 1200, 19200, 115K baud */
  302.                 switch (argv[1][1]) {
  303.                     case '2':  /* Assume 1200 Baud */                
  304.                         Baud = BAUD1200;
  305.                       break;
  306.                     case '9':  /* Assume 19200 Baud */                
  307.                         Baud = BAUD19200;
  308.                       break;
  309.                     case '1':  /* Assume 115K Baud */                
  310.                         Baud = BAUD115K;
  311.                       break;
  312.                 }                            
  313.                 break;
  314.  
  315.         case '2':                   /* Assume 2400 baud */
  316.             Baud = BAUD2400;
  317.             break;
  318.  
  319.         case '3':                   
  320.                 if ((argv[1][1]) == '8')  /* Assume 38400 baud */
  321.                 Baud = BAUD38400;
  322.                 else  /* Assume 300 baud */
  323.                 Baud = BAUD300;
  324.             break;
  325.  
  326.         case '4':                   /* Assume 4800 baud */
  327.             Baud = BAUD4800;
  328.             break;
  329.  
  330.         case '5':                   /* Assume 57K baud */
  331.             Baud = BAUD57K;
  332.             break;
  333.  
  334.         case '6':                   /* Assume 600 baud */
  335.             Baud = BAUD600;
  336.             break;
  337.  
  338.         case '9':                   /* Assume 9600 baud */
  339.             Baud = BAUD9600;
  340.             break;
  341.         }
  342.  
  343.            if(( *argv[2] == 'H' || *argv[2] == 'h'))  {
  344.                   bbs_hardwire = 1;        /* not going through modem */
  345.          }
  346.           else {
  347.                   modem_type = atoi(argv[2]);
  348.           }
  349.  
  350.         if (argc > 3)
  351.             bbs_noecho = 1;         /* Disable bbs_noecho */
  352.  
  353.     }
  354.     else  {
  355.         printf("\nFORMAT : \nbbs [baud] [mt]");
  356.         printf("\n\nWHERE:\n  baud: opening baud rate : 1200 to 155K baud");
  357.         printf("\n  mt: modem type");
  358.           printf("\n        0 = Hayes Ultra; 1 = USR Courier;     2 = Microcom QX or UDS Fastalk;");
  359.           printf("\n        3 = Telebit;     4 = MultiTech;       5 = GVC SM96;");
  360.           printf("\n        6 = Ventel;      7 = Digicom Systems; 8 = Generic type;");
  361.           printf("\n                         9 = Standard type;");
  362.           printf("\n                 H = Hardwired togeather without modem");
  363.         return;
  364.     }
  365.  
  366.     
  367.     printf("Setting up BBS on COM1 at %s, 8 data, no parity, 1 stop\n", baudstr[Baud]);
  368.     switch (xc_entr(MIN_BUFFERS)) {
  369.     case 0:
  370.         xc_link(Port, 2);
  371.         xc_init(Port, Baud, Parity, Data, Stop);
  372.         xck_link();
  373.         xct_link();
  374.           if (!bbs_hardwire){
  375.               im_setmodem(Port,modem_type,2);    
  376.             if (im_fopen(Port) < IM_OK) {
  377.                 echoln(NoModem, ECHO_SCR);
  378.                 xc_exit();
  379.                 break;
  380.             }
  381.            else
  382.                xctp_pend(Port,36);  /* pause 2 secs. */
  383.                im_spkr(Port,IM_SPKR_OFF);
  384.  
  385.           }
  386.         wclear();
  387.         sclear();
  388.         logit(logs[LOG_INTRO]);
  389.         while (abort_status != BBS_TERM) {
  390.           for (idx = 0; (idx < 1); ++idx) { /* Do it once */
  391.             if (idle() < 0)
  392.                 break;
  393.             if (modem_type == 9) /* if STANDARD_TYPE MODEM, pause in case
  394.                                     there is an MNP on the other end. Otherwise
  395.                                     the intro may get lost while the modems
  396.                                     finish negotiating */
  397.                {
  398.                xct_link();
  399.                xct_pend(18 * 2); /* wait 2 seconds */
  400.                xct_unlk();
  401.                }
  402.             if (intro() < 0) 
  403.                 break;
  404.             for (i = 0; ((is_dead() == 0) && (i < RETRIES)); ++i) {
  405.                 if (passwd(Firstname) == 0)
  406.                     break;                  /* Found the user */
  407.             }
  408.             if (i == RETRIES) {             /* Too many retries ! */
  409.                 leave(LOG_PASS);
  410.             } else {                        /* Signed on! */
  411.                 if (is_dead() == 0)         /* Handle all of the menus */
  412.                     online();
  413.                 if (is_dead() == 0) 
  414.                     leave(LOG_OFF);         /* Graceful exit */
  415.                 else {                      /* Error exit */
  416.                     switch (abort_status) {
  417.                     case BBS_TERM:
  418.                         echoln(Logoff, ECHO_SCR | ECHO_COM);
  419.                         leave(LOG_TERM);
  420.                         break;
  421.                     case USER_DISC:
  422.                         leave(LOG_CONN);    /* User lost connection */
  423.                         break;
  424.                     case USER_TIMO:
  425.                         echoln(NoResponse, ECHO_SCR | ECHO_COM);
  426.                         leave(LOG_TIMO);
  427.                         break;
  428.                     }
  429.                 }
  430.             }
  431.           }                                 /* Do it once */
  432.         }                                   /* End of while loop */
  433.  
  434.         echoln(logs[LOG_EXIT], ECHO_SCR | ECHO_COM);
  435.         logit(logs[LOG_EXIT]);
  436.  
  437.         xck_unlk();
  438.           if(!bbs_hardwire)
  439.             im_close(Port);
  440.         xc_unlk(Port);
  441.         wclear();
  442.         sclear();
  443.         xc_exit();
  444.         break;
  445.     case -1:
  446.         printf("XCOMMS is not properly installed\n");
  447.         break;
  448.     case -2:
  449.         printf("Internal error - BBS improperly exited before\n");
  450.         break;
  451.     default:
  452.         xct_unlk();
  453.         xc_exit();  
  454.         printf("Not enough buffers are allocated for BBS\n");
  455.         break;
  456.     }
  457. }
  458.  
  459. static int intro(void)
  460. {
  461.     char buffer[82];
  462.     FILE *Stream;
  463.  
  464.     if (echoln(product, ECHO_SCR | ECHO_COM) < 0)
  465.         return(-1);
  466.     if (echoln(copyr1, ECHO_SCR | ECHO_COM) < 0)
  467.         return(-1);
  468.      Stream = fopen(int_file, "r");
  469.     if (Stream)  {
  470.         while (fgets(buffer, 80, Stream) != NULL) {
  471.             if (echoln(buffer, ECHO_SCR | ECHO_COM) < 0)
  472.                 return(-1);
  473.         }
  474.         fclose(Stream);
  475.     }
  476.     return(0);
  477. }
  478.  
  479. /*
  480.     logit   Add the character string to the current log file - append
  481.             the date and time.  Also, report this status to the user
  482.             on the status line automatically.  
  483. */
  484.  
  485. static char *logit(char *string)
  486. {
  487.  
  488.     FILE *Stream;
  489.      Stream = fopen(log_file, "a+");
  490.     if (Stream)  {
  491.         strncpy(logbuf, string, 80);
  492.         strcat(logbuf, " ");
  493.         strcat(logbuf, tod());
  494.         dfield(MAIN_STAT);
  495.         fputs(logbuf, Stream);
  496.         fclose(Stream);
  497.     } 
  498.     return(0);                              /* Status is ignored */
  499. }
  500.  
  501.  
  502.  
  503. /*
  504.     is_dead     VERY IMPORTANT!
  505. */
  506.  
  507. static int is_dead(void)
  508. {
  509.     int status = -1;                    /* Assume all failed */
  510.     if (abort_status  == BBS_OK) {
  511.         if (is_break() == 0) {
  512.             if (comm_status == COMM_CONN) {
  513.                 if (xc_dcd(Port) == 0) {
  514.                     abort_status = USER_DISC;
  515.                 } else {                /* Connection (DCD) still on */
  516.                     status = 0;
  517.                 }
  518.                 if (timeoutf) {         /* Waiting for user input */
  519.                     if (xct_test() == 0) {
  520.                         timeoutf = 0;   /* Ignore the timeoutf now */
  521.                         abort_status = USER_TIMO;
  522.                         status = -1;
  523.                     }
  524.                 }
  525.             } else {                    /* No connection anyways ... */
  526.                 status = 0;
  527.             }
  528.         } else {                        /* User pressed Ctrl-Break */
  529.             abort_status = BBS_TERM;
  530.         }
  531.     }
  532.   if (!bbs_hardwire || (abort_status == BBS_TERM))
  533.       return(status);
  534.   else
  535.       return(0);
  536.  
  537. }
  538.  
  539. static int is_break(void)  /* Test for the presence of a Ctrl-Break abort */
  540. {               /* This does not assume a catestrophic error! */
  541.     int status;
  542.  
  543.      status = xck_test();
  544.     if (status) {          /* Ctrl-Break pressed */
  545.         while (xck_keyt())
  546.             xck_getc();
  547.     }
  548.     return(status);
  549. }
  550.  
  551. static int passwd(         /* Log in the user return a 0 if OK, -1 if in error */
  552. char *prompt)       /* Will not let user login as BBS */
  553. {
  554.     char    buff3[81];
  555.     char    buffer[81];
  556.     char    real_pwd[81];
  557.     int     status = 0;            /* Assume all is OK */
  558.  
  559. /*  Ask the user for first and last name */
  560.  
  561.     real_pwd[0] = CTRL_Z; 
  562.     real_pwd[1] = '\n';
  563.     real_pwd[2] = '\000';
  564.     echoln(prompt, ECHO_SCR | ECHO_COM);
  565.     getinput(Username, ECHO_SCR | ECHO_COM | INPT_UPR | INPT_KEY | INPT_COM);
  566.  
  567. /*  Now search for existence of it */
  568.  
  569.     if (is_dead())
  570.         return(-1);             /* OOPS - DROPPED CONNECTION */
  571.  
  572.     if  (search(real_pwd, Username) == 0) {         /* Found the entry */
  573.         echoln(Password, ECHO_SCR | ECHO_COM);
  574.         getinput(buff3,ECHO_SCR|ECHO_COM|INPT_UPR|INPT_KEY|ECHO_DOT|INPT_COM);
  575.         strcat(buff3, "\n");
  576.         if (is_dead())
  577.             return(-1);             /* OOPS - DROPPED CONNECTION */
  578.         if (strcmp(buff3, real_pwd) == 0) {
  579.             echoln(Thanks, ECHO_SCR | ECHO_COM);
  580.             strcpy(buffer, Username);
  581.             strcat(buffer, logs[LOG_OLD]);
  582.             logit(buffer);
  583.         } else {
  584.             status = -1;
  585.             echoln(Illpass, ECHO_SCR | ECHO_COM);
  586.         }
  587.     } else {                            /* New user */
  588.         echoln(Hellonew, ECHO_SCR | ECHO_COM);
  589.         getinput(buff3,ECHO_SCR|ECHO_COM|INPT_UPR|INPT_KEY|ECHO_DOT|INPT_COM);
  590.         add(buff3);
  591.         strcpy(buffer, Username);
  592.         strcat(buffer, logs[LOG_NEW]);
  593.         logit(buffer);
  594.     }
  595.     comm_status = COMM_CONN;            /* User is now connected */
  596.     return(status);   
  597. }
  598.  
  599. static int add(       /* Add a username, password, and original date */
  600. char *password)
  601. {
  602.     char    buffer[81];
  603.     FILE    *Stream;
  604.  
  605.     Stream = fopen(pas_file, "a+");
  606.     strcpy(buffer, Username);
  607.     strcat(buffer, "\n");
  608.     fputs(buffer, Stream);
  609.     strcpy(buffer, password);
  610.     strcat(buffer, "\n");
  611.     fputs(buffer, Stream);
  612.     fputs(tod(), Stream);
  613.     fclose(Stream);
  614.     return(0);    
  615. }
  616.  
  617. /*  User BBS is the default and is quickly qualified  */
  618. static int search(          /* Search the password data base for the Username */
  619. char *pwd,                  /* Return the password if found */
  620. char *name)                 /* Given the name to search */
  621. {
  622.     int status = -1;    /* Assume that there is none */
  623.     char    buffer[81];
  624.     char    _user[81];
  625.     FILE    *Stream;
  626.  
  627.     if (strcmp(name, bbs) != 0) {
  628.         
  629.     if ((Stream = fopen(pas_file, "r")) != NULL) {
  630.     strcpy(_user, name);
  631.     strcat(_user, "\n");
  632.         while ( (char *) fgets(buffer,  80, Stream) != NULL) {
  633.             if (strcmp(buffer, _user) == 0) {
  634.                 fgets(pwd, 80, Stream);       /* Return the password */
  635.                 status = 0;                   /* Signal successful search */
  636.                 break;
  637.             } else {
  638.                 fgets(buffer, 80, Stream);    /* Read past password */
  639.                 fgets(buffer, 80, Stream);    /* And startup date */
  640.             }
  641.         }
  642.         fclose(Stream);
  643.     }    
  644.     } else
  645.         status = 0;
  646.     return(status);
  647. }
  648.  
  649.  
  650. static int online(void)    /* Return a 0 if user wishes to exit, -1 if error */
  651. {           /* Stay here as long as user is using the menus */
  652.     int i;
  653.     char    buffer[81];
  654.     int exitflag = 0;
  655.     while (exitflag == 0) {
  656.         for (i = 0;(*Menu[i]);++i) {    /* Display the user online options */
  657.             echoln(Menu[i], ECHO_SCR | ECHO_COM);
  658.         }
  659.         getinput(buffer, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM | INPT_UPR);
  660.         if (echoln("\n", ECHO_SCR | ECHO_COM) < 0)
  661.             return(-1);
  662.         switch (buffer[0]) {
  663.         case 'R':
  664.             read_msg(ECHO_SCR | ECHO_COM, INPT_KEY | INPT_COM);
  665.             break;
  666.         case 'S':
  667.             send_msg(ECHO_SCR | ECHO_COM, INPT_KEY | INPT_COM);
  668.             break;
  669.         case 'C':
  670.             chat();
  671.             break;
  672.         case 'U':
  673.             upload();
  674.             break;
  675.         case 'D':
  676.             download();
  677.             break;
  678.         case 'F':
  679.             files(ECHO_SCR | ECHO_COM | INPT_COM | INPT_KEY);
  680.             break;
  681.         case 'V':
  682.             typefile();
  683.             break;
  684.         case 'Q':
  685.             exitflag = 1;
  686.             break;
  687.         default:
  688.             echoln(Oops, ECHO_SCR | ECHO_COM);
  689.  
  690.             break;
  691.         }
  692.     }
  693.     return(0);    /* User wishes to exit now */
  694. }
  695.  
  696. static int download(void)
  697.     int row, column;
  698.     char answer[81];
  699.     char buffer[81];
  700.     int status;
  701.     int index;
  702.      char protocol;
  703.  
  704.      status = 1;
  705.      while(status)
  706.          {
  707.         echoln("\n\nDownload Choices Are:\n\n" , ECHO_SCR | ECHO_COM);
  708.         echoln("X  XMODEM\n", ECHO_SCR | ECHO_COM);
  709.         echoln("M  XMODEM 1K\n", ECHO_SCR | ECHO_COM);
  710.          echoln("Y  YMODEM\n", ECHO_SCR | ECHO_COM);
  711.         echoln("K  KERMIT\n", ECHO_SCR | ECHO_COM);
  712.         echoln("Q  QUIT\n", ECHO_SCR | ECHO_COM);
  713.           echoln("\n Enter your choice: ", ECHO_SCR | ECHO_COM);
  714.  
  715.          getinput(answer, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM | INPT_UPR);
  716.          switch(answer[0])
  717.              {
  718.              case 'X':
  719.              case 'M':
  720.              case 'Y':
  721.              case 'K':
  722.                  {
  723.                  status = 0;
  724.                  protocol = answer[0];
  725.                  break;
  726.                  }
  727.              case 'Q':
  728.                  return(0);
  729.              default:
  730.                 echoln("\n\n\007Invalid Response\n\n", ECHO_SCR | ECHO_COM);
  731.              }
  732.          }
  733.  
  734.      echoln(Downfile, ECHO_SCR | ECHO_COM);
  735.      getinput(answer, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM | INPT_UPR);
  736.      echoln(Getready, ECHO_SCR | ECHO_COM);
  737.  
  738.     xcv_gcur(&row, &column);
  739.     xcv_scur(STATUSROW, 0);
  740.     dfield(NULL_STR);
  741.  
  742.      switch(protocol)
  743.          {
  744.          case 'X':
  745.              index = XMODEM + (- ( status = xmk_putf(Port, answer, xmodeminfo, 1,
  746.                                                             XMODEM_128,XMODEM_CRC)));
  747.              break;
  748.          case 'M':
  749.              index = XMODEM + (- ( status = xmk_putf(Port, answer, xmodeminfo, 1,
  750.                                                             XMODEM_1K,XMODEM_CRC)));
  751.              break;
  752.          case 'Y':
  753.              xct_pend(18*10);        /* pause for 10 seconds */
  754.              index = XMODEM + (- ( status = ym_putf(Port, answer, 1, 1)));
  755.             index = (index == 0) ? 0 : -2;
  756.              break;
  757.          case 'K':
  758.              xct_pend(18*10);        /* pause for 10 seconds */
  759.              index = XMODEM + (- ( status = km_putf(Port, answer, 1, 1)));
  760.             index = (index == 0) ? 0 : -2;
  761.             break;
  762.              }
  763.  
  764.     
  765.                                                         
  766.      xcv_scur(row, column);
  767.     echoln(logs[index], ECHO_SCR | ECHO_COM);
  768.     strcpy(buffer, answer);         /* Log it */
  769.     strcat(buffer, " ");
  770.     strcat(buffer, logs[index]);
  771.     logit(buffer);
  772.     main_menu();
  773.     return(status);
  774. }
  775.  
  776. static int upload(void)    /* XMODEM upload */
  777. {
  778.     int row, column;
  779.     char desc[81];
  780.     char buffer[81];
  781.     char answer[81];
  782.     int status;
  783.     FILE *Stream;
  784.     int  index;
  785.      char protocol;
  786.  
  787.      status = 1;
  788.      while(status)
  789.          {
  790.         echoln("\n\nUpload Choices Are:\n\n" , ECHO_SCR | ECHO_COM);
  791.         echoln("X  XMODEM\n", ECHO_SCR | ECHO_COM);
  792.         echoln("M  XMODEM 1K\n", ECHO_SCR | ECHO_COM);
  793.          echoln("Y  YMODEM\n", ECHO_SCR | ECHO_COM);
  794.         echoln("K  KERMIT\n", ECHO_SCR | ECHO_COM);
  795.         echoln("Q  QUIT\n", ECHO_SCR | ECHO_COM);
  796.           echoln("\n Enter your choice: ", ECHO_SCR | ECHO_COM);
  797.  
  798.          getinput(answer, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM | INPT_UPR);
  799.          switch(answer[0])
  800.              {
  801.              case 'X':
  802.              case 'M':
  803.              case 'Y':
  804.              case 'K':
  805.                  {
  806.                  status = 0;
  807.                  protocol = answer[0];
  808.                  break;
  809.                  }
  810.              case 'Q':
  811.                  return(0);
  812.              default:
  813.                 echoln("\n\n\007Invalid Response\n\n", ECHO_SCR | ECHO_COM);
  814.              }
  815.          }
  816.  
  817.  
  818.      if((protocol != 'K') && (protocol != 'Y'))
  819.          {
  820.          echoln(Upfile, ECHO_SCR | ECHO_COM);
  821.         getinput(answer, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM | INPT_UPR);
  822.          }
  823.     echoln(Getready, ECHO_SCR | ECHO_COM);
  824.  
  825.     xcv_gcur(&row, &column);
  826.     xcv_scur(STATUSROW, 0);
  827.     dfield(NULL_STR);
  828.  
  829.      switch(protocol)
  830.          {
  831.          case 'X':
  832.              index = XMODEM + (- ( status = xmk_getf(Port, answer, xmodeminfo, 1,
  833.                                                             XMODEM_128,XMODEM_CRC)));
  834.              break;
  835.          case 'M':
  836.              index = XMODEM + (- ( status = xmk_getf(Port, answer, xmodeminfo, 1,
  837.                                                             XMODEM_1K,XMODEM_CRC)));
  838.              break;
  839.          case 'Y':
  840.              xct_pend(18*10);        /* pause for 10 seconds */
  841.              index = XMODEM + (- ( status = ym_getf(Port, "", 1, 1)));
  842.             index = (index == 0) ? 0 : -2;
  843.              break;
  844.          case 'K':
  845.              xct_pend(18*10);        /* pause for 10 seconds */
  846.              index = XMODEM + (- ( status = km_getf(Port, "", 1, 1)));
  847.             index = (index == 0) ? 0 : -2;
  848.             break;
  849.              }
  850.     
  851.      
  852.      xcv_scur(row, column);
  853.     echoln(logs[index], ECHO_SCR | ECHO_COM);
  854.  
  855.     strcpy(buffer, answer);         /* Log it */
  856.     strcat(buffer, " ");
  857.     strcat(buffer, logs[index]);
  858.     logit(buffer);
  859.  
  860.     if (status >= XM_OK) {          /* If successful, then write it */
  861.         echoln(Descrip, ECHO_SCR | ECHO_COM);
  862.         getinput(desc, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM);
  863.         if (desc[0] >= ' ') {
  864.             if ((Stream = fopen(dir_file, "a+")) != NULL) {
  865.                 fprintf(Stream, "%-15s %s\n", answer, desc, buffer);
  866.                 fclose(Stream);
  867.             }
  868.         }
  869.         echoln(Textend, ECHO_SCR | ECHO_COM);
  870.     }
  871.     main_menu();
  872.     return(status);
  873.  }
  874.  
  875. static int files( /* Display THE DIRECTORY */
  876. int display)
  877.     int  status = 0;
  878.     FILE *Stream;
  879.     char buffer[81];
  880.  
  881.     if ((Stream = fopen(dir_file, "r")) == NULL) {
  882.         echoln(Nofile, display);
  883.     } else {
  884.         while (fgets(buffer, 80, Stream) != NULL) {
  885.             if (echoln(buffer, display) < 0)
  886.                 return(-1);
  887.         }
  888.         fclose(Stream);
  889.     }
  890.     return(status);
  891. }
  892.  
  893.  
  894. static int typefile(void)
  895.     int  status = 0;
  896.     FILE *Stream;
  897.     char buffer[81];
  898.     char filename[81];
  899.  
  900.     echoln(Whatfile, ECHO_SCR | ECHO_COM);
  901.     getinput(filename, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM);
  902.     echoln("\n", ECHO_SCR | ECHO_COM);
  903.  
  904.     if ((Stream = fopen(filename, "r")) == NULL) {
  905.         echoln(Nofilex, ECHO_SCR | ECHO_COM);
  906.     } else {
  907.         while (fgets(buffer, 80, Stream) != NULL) {
  908.             if (echoln(buffer, ECHO_SCR | ECHO_COM) < 0)
  909.                 return(-1);         /* OOPS - DROPPED CONNECTION */
  910.         }
  911.         fclose(Stream);
  912.     }
  913.     return(status);
  914. }
  915.  
  916. static int send_msg( /* 0 if sent OK, 1 if no user, -1 if error */
  917. int display,
  918. int inputd)
  919.     int     status = 0;
  920.     FILE    *Stream;
  921.     char    buffer[81];
  922.     char    receivr[81];
  923.     int     exitflag = 0;
  924.  
  925.     echoln(Towhom, display);
  926.     getinput(receivr, display | INPT_UPR | inputd);
  927.     if (search(buffer, receivr) == 0) {
  928.  
  929.         Stream = fopen(msg_file, "a+");
  930.         strcpy(buffer, receivr);
  931.         strcat(buffer, "\n");
  932.         fputs(buffer, Stream);
  933.         strcpy(buffer, Username);
  934.         strcat(buffer, "\n");
  935.         fputs(buffer, Stream);
  936.         fputs(tod(), Stream);
  937.         echoln(Chat1, display);
  938.         while (exitflag == 0) {
  939.             if (is_dead())
  940.                 return(-1);             /* OOPS - DROPPED CONNECTION */
  941.             getinput(buffer, display | inputd);
  942.             echoln("\n", display);
  943.             if (buffer[0] == CTRL_Z) {
  944.                 exitflag = 1;
  945.                 buffer[0] = '^';
  946.                 buffer[2] = '\000';
  947.             }
  948.             strcat(buffer, "\n");
  949.             fputs(buffer, Stream);
  950.         }
  951.         fclose(Stream);
  952.     } else {
  953.         echoln(Nouser, display);
  954.         status = 1;
  955.     }
  956.     return(status);
  957. }
  958.  
  959.  
  960. static int read_msg(   /* 0 if message, 1 no message, -1 error */
  961. int display,
  962. int inputd)
  963.     int  status =  1;               /* Assume no message read */
  964.     FILE *INStream;
  965.     FILE *OUTStream;
  966.     char buffer[81];
  967.     char _name[81];
  968.  
  969.     if ((INStream = fopen(msg_file, "r")) != NULL) {
  970.         OUTStream = fopen(msg_temp, "w");
  971.         strcpy(_name, Username);
  972.         strcat(_name, "\n");
  973.  
  974.         while (fgets(buffer, 80, INStream) != NULL) {
  975.             if (is_dead())
  976.                 return (-1);        /* OOPS - DROPPED CONNECTION */
  977.             if (strcmp(buffer, _name) == 0) {
  978.                 status = 0;
  979.                 echoln(Msgfrom, display);
  980.                 echoln(fgets(buffer, 80, INStream), display);
  981.                 echoln(Msgwhen, display);
  982.                 echoln(fgets(buffer, 80, INStream), display);
  983.                 echoln(Msgstart, display);
  984.                 while (fgets(buffer, 80, INStream) != NULL) {
  985.                     if (buffer[0] == '^')
  986.                         break;
  987.                     echoln(buffer, display);
  988.                 }
  989.                 while (fgets(buffer, 80, INStream) != NULL) {
  990.                     fputs(buffer, OUTStream);
  991.                 }
  992.                 echoln(Msgend, display);
  993.             } else {
  994.                 fputs(buffer, OUTStream);
  995.                 while (fgets(buffer, 80, INStream) != NULL) {
  996.                     fputs(buffer, OUTStream);
  997.                     if (buffer[0] == '^')
  998.                         break;
  999.                 }
  1000.             }
  1001.         }
  1002.  
  1003.         fclose(INStream);
  1004.         fclose(OUTStream);
  1005.         if (status == 0) {
  1006.             echoln(Delmsg, display);
  1007.             getinput(buffer, display | inputd);
  1008.             if ((buffer[0] == 'Y') || (buffer[0] == 'y')) {
  1009.                 unlink(msg_file);
  1010.                 rename(msg_temp, msg_file);
  1011.             }
  1012.         }        
  1013.     }
  1014.     if (status == 1)
  1015.         echoln(No_msg, display);
  1016.     return(status);
  1017. }
  1018.  
  1019. static int chat(void)
  1020.     char    buffer[81];
  1021.  
  1022.     echoln(Chat1, ECHO_SCR | ECHO_COM);
  1023.     do {
  1024.         getinput(buffer, ECHO_SCR | ECHO_COM | INPT_KEY | INPT_COM);
  1025.         if (echoln("\n", ECHO_SCR | ECHO_COM) < 0)
  1026.             return(-1);                 /* EXIT DUE TO ERROR */
  1027.     } while (buffer[0] != CTRL_Z);
  1028.     return(0);
  1029. }
  1030.  
  1031.  
  1032. /*      ================== DISCONNECT ================== */
  1033.  
  1034. static int leave(    /*  Hang up the modem */
  1035. int reason)
  1036. {
  1037.     char    buffer[81];
  1038.  
  1039.     echoln(Byebye, ECHO_SCR | ECHO_COM);    /* Tell the user to hangup */
  1040.     strcpy(buffer, Username);               /* Log the occurence */
  1041.     strcat(buffer, logs[reason]);
  1042.     logit(buffer);
  1043.     comm_status  = COMM_IDLE;               /* Communications now down */
  1044.     im_hangu(Port);                         /* Force the connection down */
  1045.     return(0);                              /* Leave abort_status alone */
  1046. }
  1047.  
  1048. static int idle(void)    /* Wait for the modem to ring */
  1049.              /* Return a -1 if BBS hit Ctrl-Break or the baud rate code */
  1050. {
  1051.     char    buffer[81];
  1052.     int     ch;
  1053.     int     status;
  1054.  
  1055.     xc_init(Port, Baud, Parity, Data, Stop);
  1056.     Username[0] = '\000';
  1057.     comm_status = COMM_IDLE; /* === SESSION STATUS === */
  1058.     abort_status = BBS_OK; /* === SESSION STATUS === */
  1059.     main_menu();
  1060.  
  1061. /*  Answer the ring */
  1062.  
  1063.     while (1) {  
  1064.           if (!bbs_hardwire){
  1065.                 if (xc_ri(Port) != 0)    /*  Have a ring ? ... */
  1066.                     break;
  1067.           }
  1068.           else  {  /* direct conection */
  1069.                     break;
  1070.           }
  1071.         if (xck_keyt()) {       /* BBS user want to do F1 options? */
  1072.             ch = xck_getc();
  1073.             if (ch == FK1) {
  1074.                 options();
  1075.             } else if ((ch & 0xFF) == RET) {
  1076.                 break;          /* Direct connect forced by BBS owner */
  1077.             }
  1078.         }
  1079.           if (is_break()){
  1080.                 abort_status = BBS_TERM;
  1081.                 return(-1);
  1082.           }
  1083.     }
  1084.     strcpy(buffer, logs[LOG_RING]);
  1085.     logit(buffer);
  1086.  
  1087.      if (!bbs_hardwire){
  1088.         if ((status = im_answ(Port)) <= IM_OK)
  1089.             return(status);        /* Answer the phone */
  1090.          else  {
  1091.             if(modem_type == IM_STANDARD_TYPE)
  1092.                   Baud = status;
  1093.             /* pause 2 seconds for new connection to stablize */
  1094.             xctp_pend(Port,36);
  1095.         }
  1096.      }
  1097.  
  1098. /*    else
  1099.               Baud = BAUD9600; */       /*   hardwire set to 9600 baud   */
  1100.  
  1101.     xc_init(Port, Baud, Parity, Data, Stop);
  1102.     xc_flush(Port);
  1103.  
  1104. /*  The phone has been answered */
  1105.  
  1106.     comm_status  = COMM_CONN; /* === SESSION STATUS === */
  1107. /*
  1108.     if (getinput(buffer, INPT_COM) < 0)
  1109.         return(-1);
  1110. */
  1111.     strcpy(buffer, logs[LOG_SON]);
  1112.     strcat(buffer, baudstr[Baud]);
  1113.     logit(buffer);
  1114.     main_menu();
  1115.     return(Baud);
  1116. }
  1117.  
  1118. static int echoln(  /* String write, return a -1 if error */
  1119. char *string,
  1120. int option)
  1121. {   
  1122.     int status = 0;
  1123.     char *ch_ptr = string;
  1124.     while (*ch_ptr) {
  1125.         if (*ch_ptr == '\n')
  1126.             status = echo(RET, option);
  1127.         status = echo(*ch_ptr, option);
  1128.           ch_ptr++;
  1129.     }
  1130.     return(status);
  1131. }
  1132.  
  1133. static int echo( /* Display a character & optionally scroll up one line */
  1134. char ch,            /* Return a 0 meaning success or a -1 if we must exit */
  1135. int  option)
  1136. {
  1137.     int oldrow, oldcol;
  1138.  
  1139.     if (is_dead())                  /* Check the connection */
  1140.         return(-1);
  1141.  
  1142.     /* Echo on the screen only if <bbs_noecho> flag is set to 0 */
  1143.  
  1144.     if ((option & ECHO_SCR) && (bbs_noecho == 0)) { /* Display on the screen */
  1145.         xcv_wtty( (char)((char)(option & ECHO_DOT) ? (char)'.' : (char)ch));
  1146.         if (xck_keyt()) {
  1147.             if ((xck_getc() & 0xFF) == XOFF) {
  1148.                 while ((xck_getc() & 0xFF) != XON) {
  1149.                     if (is_dead())
  1150.                         return(-1);     /* **** OOPS - LOST CONNECTION */
  1151.                 }
  1152.             }
  1153.         }
  1154.         xcv_gcur(&oldrow, &oldcol);
  1155.         if (oldrow == STATUSROW) {
  1156.             window(0, STATUSROW, SCRWIDTH, (char)attr_text, SCROLL);
  1157.             xcv_scur(oldrow - 1, oldcol);
  1158.         }
  1159.     } 
  1160.     /* Display to the comms user  only if a session is on */
  1161.  
  1162.     if ((option & ECHO_COM) && (comm_status == COMM_CONN)) {
  1163.         if (xc_test(Port)) {
  1164.             if ((xc_getc(Port) & 0xFF) == XOFF) {
  1165.                 while ((xc_getc(Port) & 0xFF) != XON) {
  1166.                     if (is_dead())
  1167.                         return(-1);     /* **** OOPS - LOST CONNECTION */
  1168.                 }
  1169.                     ;
  1170.             }
  1171.         }
  1172.         xc_putc(Port, (char)((char)(option & ECHO_DOT) ? (char)'.' : (char)ch));
  1173.     }
  1174.     return(0);                      /* Always succeeds! */
  1175. }
  1176.  
  1177. /*
  1178.     getinput - Given the character string buffer address, accept the
  1179.     user input string and return the number of characters entered.  Accept
  1180.     input at the current cursor location.  There is a limit of 80 characters.
  1181.     Returns:
  1182.  
  1183.         0   Only Enter key pressed
  1184.         >0  The character string of n characters returned
  1185.         -1  Connection down via timeout or otherwise
  1186. */
  1187. static int getinput(
  1188. char buffer[],
  1189. int  option)
  1190. {
  1191.     int i = 0;
  1192.     int exitflag = 0;
  1193.     int got_one;
  1194.     char ch;
  1195.  
  1196.     timeoutf = 1;
  1197.     xct_set(TIMEOUT);               /* Start the timeout */
  1198.  
  1199.     while (exitflag == 0) {
  1200.         if (is_dead())              /* ************************* */
  1201.             return(-1);             /* OOPS - lost the session ! */
  1202.         got_one = 0;
  1203.         if (xck_keyt() && (option & INPT_KEY)) {
  1204.             got_one = 1;
  1205.             ch = (char)xck_getc();
  1206.         } else if (xc_test(Port) && (option & INPT_COM)) {
  1207.             got_one = 1;
  1208.             ch = (char)xc_getc(Port);
  1209.         }
  1210.         if (got_one) {
  1211.         if (i >= 80) {
  1212.             buffer[i] = '\000';
  1213.             exitflag = 1;
  1214.             break;
  1215.         }
  1216.         if (option & INPT_UPR) {
  1217.             if ((ch >= 'a') && (ch <= 'z'))
  1218.                 ch = ch - ('a' - 'A');
  1219.         }
  1220.         switch ((ch) & 0xFF) {
  1221.         case RET:
  1222.             buffer[i] = '\000';
  1223.             exitflag = 1;               /* Exit file entry */
  1224.             break;
  1225.         case RUB1:
  1226.         case RUB2:
  1227.             if (i) {
  1228.                 --i;
  1229.                 echo(RUB1, option & (~ ECHO_DOT));
  1230.                 echo(' ', option & (~ ECHO_DOT));
  1231.                 echo(RUB1, option & (~ ECHO_DOT));
  1232.             }
  1233.             break;
  1234.         default:
  1235.             buffer[i++] = ch;
  1236.             if (ch == CTRL_Z) {
  1237.                 echo('^', option);
  1238.                 echo('Z', option);
  1239.             } 
  1240.             if ((ch >= ' ') && (ch <= RUB2))
  1241.                 echo(ch, option);
  1242.             }
  1243.         }
  1244.     }
  1245.     timeoutf = 0;                       /* Reset the flag */
  1246.     return(i);                          /* Return size of answer */
  1247. }
  1248.  
  1249. static int main_menu(void)
  1250. {
  1251.     sclear(); 
  1252.     if (comm_status == COMM_IDLE)
  1253.         dfield(MAIN_F1);             
  1254.     dfield(MAIN_EXIT);
  1255.     dfield(MAIN_STAT);
  1256.     return(0);                      /* Always successful! */
  1257. }
  1258.  
  1259. static int options(void)                       /* Display THE OPTIONS */
  1260. {
  1261.     char _old_user[81];
  1262.     char name[81];
  1263.     char desc[81];
  1264.     char buffer[81];
  1265.     FILE *Stream;
  1266.  
  1267.     sclear(); 
  1268.     dfield(OPTN_F1);
  1269.     dfield(OPTN_F2);
  1270.     dfield(OPTN_F3);
  1271.     dfield(OPTN_F4);
  1272.     dfield(OPTN_EXIT);
  1273.     wclear();
  1274.     echoln(Opt_inst, ECHO_SCR);
  1275.     for (;;) {
  1276.         if (is_break()) {
  1277.             wclear();
  1278.             break;
  1279.         }
  1280.         if (xck_keyt()) {
  1281.             switch (xck_getc()) {
  1282.             case FK1:
  1283.                 strcpy(_old_user, Username);
  1284.                 strcpy(Username, "BBS");
  1285.                 send_msg(ECHO_SCR, INPT_KEY);
  1286.                 strcpy(Username, _old_user);
  1287.                 echoln("\n", ECHO_SCR);
  1288.                 break;
  1289.             case FK2:
  1290.                 strcpy(_old_user, Username);
  1291.                 strcpy(Username, "BBS");
  1292.                 read_msg(ECHO_SCR, INPT_KEY);
  1293.                 strcpy(Username, _old_user);
  1294.                 echoln("\n", ECHO_SCR);
  1295.                 break;
  1296.             case FK3:
  1297.                 files(ECHO_SCR | INPT_KEY);
  1298.                 echoln("\n", ECHO_SCR);
  1299.                 break;
  1300.             case FK4:
  1301.                 echoln(Filereq, ECHO_SCR);
  1302.                 getinput(name, ECHO_SCR | INPT_KEY | INPT_UPR);
  1303.                 if ((Stream = fopen(name, "r")) == NULL) {
  1304.                     echoln(Nofilex, ECHO_SCR);
  1305.                 } else {
  1306.                     fclose(Stream);
  1307.                     echoln(Descrip, ECHO_SCR);
  1308.                     getinput(desc, ECHO_SCR | INPT_KEY);
  1309.                     if ((Stream = fopen(dir_file, "a+")) != NULL) {
  1310.                         fprintf(Stream, "%-15s %s\n", name, desc, buffer);
  1311.                         fclose(Stream);
  1312.                     }
  1313.                     echoln(Textend, ECHO_SCR);
  1314.                 }
  1315.                 break;
  1316.                 case 0:                    /* can get this on Ctrl-Break */
  1317.                  is_break();
  1318.                  wclear();
  1319.                     main_menu();
  1320.                     return(0);                      /* Always successful! */
  1321.                 }
  1322.             echoln(Opt_inst, ECHO_SCR);
  1323.  
  1324.         }
  1325.     }
  1326.     main_menu();
  1327.     return(0);                      /* Always successful! */
  1328. }
  1329.  
  1330.  
  1331. /*
  1332.     window - perform a window scroll up or clear for an entire line
  1333.              or lines given the attribute
  1334.  
  1335. */
  1336. static int window(
  1337. int row,                            /* Row address starting at 0 */
  1338. int row_count,                      /* Number of rows to scroll or clear */
  1339. int column,                         /* Last column number */
  1340. char attribute,                     /* Attribute for the window */
  1341. int flag)                           /* SCROLL or CLEARS flag */
  1342. {
  1343.     xcv_scrl(row, 0, row + row_count - 1, column, attribute, flag);    
  1344.     return(0);                      /* Always succeeds! */
  1345. }
  1346.  
  1347. static void sclear(void)                  /* Clear status line */
  1348. {
  1349.     window(STATUSROW, 1, SCRWIDTH, (char)attr_text, CLEARS);
  1350.  
  1351. }
  1352.  
  1353. static void wclear(void)                        /* Clear window text area */
  1354. {
  1355.     xcv_scur(0, 0);                 /* Home cursor */
  1356.     window(0, STATUSROW, SCRWIDTH, (char)attr_text, CLEARS);
  1357. }
  1358.  
  1359. /*
  1360.     dfield - display field on the bottom line using the 
  1361.              attr_status attribute.  The cursor is not moved.
  1362. */
  1363. static int dfield(
  1364. int index)                          /* Index into text array */
  1365. {
  1366.     char _string[MAXFIELD];         /* Maximum string field width */
  1367.     int i;                          /* Counter variable */
  1368.     int width = text[index].wid;    /* Maximum LEGAL field width */
  1369.     int column = text[index].col;   /* Number of columns */
  1370.     char *string = text[index].str;
  1371.     int oldrow, oldcol;             /* Old cursor address */
  1372.  
  1373.     if (width > MAXFIELD)
  1374.         width = MAXFIELD;           /* Specified field is too big */
  1375.                                     /* Create the fixed field */
  1376.     for (i = 0; (_string[i] = *string++) >= ' '; ++i)
  1377.         ;
  1378.     for (; (i < width); ++i)
  1379.         _string[i] = ' ';
  1380.     xcv_gcur(&oldrow, &oldcol);     /* Save the cursor location */
  1381.     
  1382.                                     /* Write out the field */
  1383.     for (i = 0; (i < width); ++i) {
  1384.         xcv_scur(STATUSROW, column + i);
  1385.         xcv_chat(_string[i], attr_status);    
  1386.     }
  1387.     xcv_scur(oldrow, oldcol);       /* Restore the cursor */
  1388.     return(0);                      /* Always succeeds! */
  1389. }
  1390.  
  1391.  
  1392. /*
  1393.     bbstod.c    - Return the time of day
  1394.  
  1395.     Copyright (C) 1986, 1987, 1988 Essential Software Incorporated
  1396.     Copyright (C) 1986, 1987, 1988 Advanced Firmware Engineering
  1397.  
  1398.     Return a character string indicating the date and time and \n
  1399.  
  1400.                10        20   25
  1401.       ....|....|....|....|....|
  1402.       DAY MM/DD/YY HH:MM:SS.hh\n        
  1403. */
  1404.  
  1405. static char *int2asc(
  1406. int ivalue)
  1407. {
  1408.     int scratch;
  1409.     intbuffer[2] = '\000';
  1410.     scratch = ivalue / 10;
  1411.     intbuffer[0] = (char) scratch + '0';
  1412.     intbuffer[1] = (char) (ivalue - (scratch * 10)) + '0';
  1413.  
  1414.     return(intbuffer);
  1415. }
  1416.  
  1417. static char *tod(void)                 /* Return the time-of-day */
  1418. {
  1419.     packet.breg.AH = 0x2A;
  1420.     i86_int(0x21, &packet);         /* Get the date */
  1421.     strcpy(buffer, days[(int) packet.breg.AL]);
  1422.     strcat(buffer, int2asc(packet.breg.DH)); strcat(buffer, "/");
  1423.     strcat(buffer, int2asc(packet.breg.DL)); strcat(buffer, "/");
  1424.     strcat(buffer, int2asc(packet.wreg.CX - 1900)); strcat(buffer, " ");
  1425.  
  1426.     packet.breg.AH = 0x2C;
  1427.     i86_int(0x21, &packet);         /* Get the time */
  1428.     strcat(buffer, int2asc(packet.breg.CH)); strcat(buffer, ":");
  1429.     strcat(buffer, int2asc(packet.breg.CL)); strcat(buffer, ":");
  1430.     strcat(buffer, int2asc(packet.breg.DH)); strcat(buffer, ".");
  1431.     strcat(buffer, int2asc(packet.breg.DL)); strcat(buffer, "\n");
  1432.     return(buffer);
  1433. }
  1434.  
  1435.