home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / bbs / turbobbs / bbs.pas next >
Pascal/Delphi Source File  |  1985-08-23  |  18KB  |  684 lines

  1. program TurboBBS100;
  2.  
  3. (*******************************************************************)
  4. (*                                                                 *)
  5. (*  Turbo Bulletin Board System    -    Distribution Version 1.00  *)
  6. (*                                                                 *)
  7. (*  (c) 1985 by Robert H. Maxwell                                  *)
  8. (*              201 - 2275 West 7th Avenue,                        *)
  9. (*              Vancouver, British Columbia, CANADA                *)
  10. (*              V6K 1Y3                                            *)
  11. (*  Original System running 300/1200 baud, 24hrs: (604) 738-7811   *)
  12. (*  Written for a Kaypro 2-84 using Rixon 212A Intelligent modem   *)
  13. (*                                                                 *)
  14. (*  If you like this program, it would most appreciated if you     *)
  15. (*  sent $30 to the above address. If you choose to operate a BBS  *)
  16. (*  with it, please forward the details so you can be kept up to   *)
  17. (*  date with changes to the program.                              *)
  18. (*                                                                 *)
  19. (*  Files required for compile: BBS.PAS    (this file),            *)
  20. (*                              IO.INC     (machine dependent I/O) *)
  21. (*                              CLOCK.INC  (real-time clock I/O)   *)
  22. (*                              MAILSYS.INC (Sections named here)  *)
  23. (*                              FILESYS.INC (XMODEM code here)     *)
  24. (*                                                                 *)
  25. (*  Information files required: WELCOME.TXT (pre-sign-on message)  *)
  26. (*                              BBSLIST.TXT (list of other BBS's)  *)
  27. (*                              BBSHELP.TXT (command explanation)  *)
  28. (*                              SYSINFO.TXT (info on the system)   *)
  29. (*  Message #1 is a permanent / MESS0001.TXT (Message Help file)   *)
  30. (*  message... do not delete! \ MESSAGES.BBS (Message table)       *)
  31. (*                              FILES.BBS   (Files table)          *)
  32. (*  Clear these periodically: / COMMENTS.BBS (Comments for Sysop)  *)
  33. (*  They can grow quickly...  \ LOG.BBS     (call log file)        *)
  34. (*                              IDS.BBS     (user list)            *)
  35. (*                                                                 *)
  36. (*  .TXT files are WordStar editable; .BBS files are program data  *)
  37. (*  maintained by the program.                                     *)
  38. (*  User SYSOP is predeclared on IDS file: the password is TURBO   *)
  39. (*                                                                 *)
  40. (*******************************************************************)
  41.  
  42. const
  43.   clockin = true;  { Compile-time flags:          }
  44.   sectsin = true;  { Use to turn features on/off. }
  45.  
  46.   noecho    = false;
  47.   echo      = true;
  48.   null      = #0;
  49.   abort     = #3;
  50.   bell      = #7;
  51.   bksp      = #8;
  52.   tab       = #9;
  53.   lnfd      = #10;
  54.   cr        = #13;
  55.   pause     = #19;
  56.   esc       = #27;
  57.   space     = ' ';
  58.  
  59. type
  60.   name      = string[14];
  61.   rate      = (slow,fast);
  62.   line      = string[80];
  63.   person    = string[27];
  64.   long      = string[150];
  65.   sysid     = record
  66.                 user: person;
  67.                 exfl: byte;
  68.                 lsto: name;
  69.                 lstm: integer;
  70.                 pass: name;
  71.                 acc:  byte;
  72.                 clr:  name;
  73.                 bsp:  char;
  74.                 lnf:  char;
  75.                 upc:  boolean;
  76.                 wid:  byte;
  77.               end;
  78.   log       = record
  79.                 who:  integer;
  80.                 when: name;
  81.                 done: name;
  82.               end;
  83.   yesno     = array[boolean] of string[3];
  84.  
  85. const yn: yesno = ('NO','YES');
  86.  
  87. var
  88.   logfile:    file of log;
  89.   logrec:     log;
  90.   idfile:     file of sysid;
  91.   idrec:      sysid;
  92.   usernum:    integer;
  93.   caller:     person;
  94.   password,
  95.   timeon,
  96.   timeoff,
  97.   cs,
  98.   message:    name;
  99.   baud:       rate;
  100.   buffer:     long;
  101.   exitchar:   char;
  102.   access:     byte;
  103.   lastmess,
  104.   charcount,
  105.   lastspace,
  106.   bufpointer,
  107.   width:      integer;
  108.   controls,
  109.   printon,
  110.   local,
  111.   filesopen,
  112.   messopen,
  113.   caps,
  114.   expert:     boolean;
  115.   bl, lf, bs: char;
  116.   sec,   onsec,   offsec   : byte;
  117.   min,   onmin,   offmin   : byte;
  118.   hour,  onhour,  offhour  : byte;
  119.   date,  ondate,  offdate  : byte;
  120.   month, onmonth, offmonth : byte;
  121.   usesec, usemin, usehour  : integer;
  122.  
  123. {$I IO.INC}
  124. {$I CLOCK.INC}
  125.  
  126. procedure outfile(fname: name);
  127.  
  128.   var
  129.     wfile : text;
  130.     fchar : char;
  131.  
  132.   begin
  133.     assign(wfile,fname);
  134.     {$I-} reset(wfile) {$I+};
  135.     if IOresult <> 0 then lineout('Can''t find ' + fname + '!') else begin
  136.       clearsc;
  137.       repeat
  138.         read(wfile, fchar);
  139.         if fchar <> #$8D then begin { <-- Allows no-wrap using WordStar files}
  140.           fchar := chr(ord(fchar) and 127);
  141.           if fchar <> lnfd then charout(fchar);
  142.           if fchar = cr then charout(lf);
  143.         end;
  144.       until cancelled or eof(wfile) or not cts;
  145.       close(wfile);
  146.       unload;
  147.     end;
  148.   end;
  149.  
  150. function findid(caller: person): integer;
  151.  
  152.   var
  153.     usernum: integer;
  154.     index: integer;
  155.  
  156.   begin
  157.     usernum := 0;
  158.     index := 0;
  159.     lineout('Searching userlist...');
  160.     reset(idfile);
  161.     if not eof(idfile) then begin
  162.       repeat
  163.         index := index + 1;
  164.         read(idfile, idrec);
  165.         if idrec.user = caller then usernum := index;
  166.       until (usernum > 0) or eof(idfile);
  167.     end;
  168.     findid := usernum;
  169.   end;
  170.  
  171. {$I MAILSYS.INC}
  172. {$I FILESYS.INC}
  173.  
  174. procedure definecs;
  175.  
  176.   var
  177.     ch: char;
  178.     prompt: line;
  179.  
  180.   begin
  181.     ch := null;
  182.     while cts and not (ch in ['Q','Y']) do begin
  183.       lineout('The following input is NOT echoed until CR (RETURN) is pressed!');
  184.       prompt := 'Enter character(s) that will clear your screen (end with CR): ';
  185.       controls := true;
  186.       cs := getinput(prompt, 11, noecho);
  187.       controls := false;
  188.       clearsc;
  189.       ch := getcap(cr + lf + 'Did that do it (Y/N/Quit)? ');
  190.     end;
  191.     if ch = 'Q' then cs := lnfd;
  192.   end;
  193.  
  194. procedure definebs;
  195.  
  196.   begin
  197.     repeat
  198.       flush;
  199.       controls := true;
  200.       stringout('Type your backspace key: ');
  201.       bs := charin(echo);
  202.       controls := false;
  203.       lineout(space);
  204.     until not ((bs in [cr, tab, space, '0'..'9', 'A'..'Z', 'a'..'z']) and cts);
  205.   end;
  206.  
  207. procedure setwidth;
  208.  
  209.   var temp: name;
  210.       test, innum: integer;
  211.  
  212.   begin
  213.     repeat
  214.       temp := getinput('Enter your terminal width (chars/line): ', 14, echo);
  215.       val(temp, innum, test);
  216.     until ((test=0) and (innum in [22..132])) or (temp='') or not cts;
  217.     if test = 0 then width := innum;
  218.   end;
  219.  
  220. procedure setvideo;
  221.  
  222.   var loop: byte;
  223.       inch: char;
  224.       temp: name;
  225.  
  226.   function ctlchar(ch: char): name;
  227.  
  228.     begin
  229.       if ch > #127 then ch := chr(ord(ch) and 127);
  230.       case ch of
  231.         null..#31   : ctlchar := '^' + chr(ord(ch) + 64);
  232.         space..#126 : ctlchar := ch;
  233.         #127        : ctlchar := '<DEL>';
  234.       end;
  235.     end;
  236.  
  237.   procedure dispcontrol(ch: char);
  238.  
  239.     begin
  240.       if ch < #128 then stringout(ctlchar(ch))
  241.         else stringout(ctlchar(ch) + '(with 8th bit set)');
  242.     end;
  243.  
  244.   begin
  245.     inch := '1';
  246.     while (inch in ['1'..'9']) and cts do begin
  247.       clearsc;
  248.       lineout('Terminal parameters:' + cr + lf);
  249.       lineout('1 - Upper case only: ' + yn[caps]);
  250.       lineout('2 - Line feeds sent: ' + yn[lf = lnfd]);
  251.       lineout('3 - Prompt bell ON : ' + yn[bl = bell]);
  252.       stringout('4 - Backspace char.: ');
  253.       dispcontrol(bs);
  254.       lineout(space);
  255.       stringout('5 - Clear Screen   : ');
  256.       for loop := 1 to length(cs) do dispcontrol(cs[loop]);
  257.       lineout(space);
  258.       str(width:3, temp);
  259.       lineout('6 - Terminal width : ' + temp);
  260.       lineout(space);
  261.       inch := getcap('Enter number of parameter to change (0 to quit): ');
  262.       case inch of
  263.         '1': caps := not caps;
  264.         '2': if lf = lnfd then lf := null else lf := lnfd;
  265.         '3': if bl = bell then bl := null else bl := bell;
  266.         '4': definebs;
  267.         '5': definecs;
  268.         '6': setwidth;
  269.       end;
  270.     end;
  271.     lineout('New definitions will be saved when [G]oodbye is executed.');
  272.   end;
  273.  
  274. procedure getcomments;
  275.  
  276.   var
  277.     comfile: file of line;
  278.     linenum: integer;
  279.     temp:    line;
  280.  
  281.   begin
  282.     clearsc;
  283.     lineout('Enter comment: up to 15 lines, enter empty line to quit.');
  284.     lineout(space);
  285.     linenum := 0;
  286.     assign(comfile, 'COMMENTS.BBS');
  287.     reset(comfile);
  288.     seek(comfile, filesize(comfile));
  289.     temp := caller;
  290.     if clockin then temp := temp + '  ' + timeon;
  291.     write(comfile, temp);
  292.     repeat
  293.       linenum := linenum + 1;
  294.       str(linenum:2, temp);
  295.       stringout(temp + ': ');
  296.       temp := inputstring(echo);
  297.       if temp <> '' then write(comfile, temp);
  298.     until (temp = '') or (linenum = 15) or not cts;
  299.     close(comfile);
  300.   end;
  301.  
  302. function nextuser: integer;
  303.  
  304.   var temp: integer;
  305.  
  306.   begin
  307.     stringout('Finding space for new user: ');
  308.     temp := findid('***');
  309.     if temp = 0 then nextuser := 1 + filesize(idfile) else nextuser := temp;
  310.   end;
  311.  
  312. procedure savedefaults;
  313.  
  314.   begin
  315.     if usernum = 0 then usernum := nextuser;
  316.     with idrec do begin
  317.       user := caller;
  318.       if expert then exfl := 0 else exfl := 255;
  319.       if clockin then lsto := timeon;
  320.       lstm := messtable[count].number;
  321.       pass := password;
  322.       clr := cs;
  323.       acc := access;
  324.       bsp := bs;
  325.       lnf := lf;
  326.       upc := caps;
  327.       wid := width;
  328.     end;
  329.     seek(idfile, usernum - 1);
  330.     write(idfile, idrec);
  331.   end;
  332.  
  333. procedure disconnect;
  334.  
  335.   var
  336.     ch: char;
  337.  
  338.   begin
  339.     clearsc;
  340.     lineout('Answering question with other than "Y" or "N" returns to BBS:');
  341.     ch := getcap('Do you want to leave comments to the Sysop (Y/N)? ');
  342.     if ch = 'Y' then getcomments;
  343.     if (ch = 'N') or (ch = 'Y') or not cts then begin
  344.       connecttime;
  345.       lineout('Thanks for calling, ' + caller);
  346.       savedefaults;
  347.       hangup;
  348.     end;
  349.   end;
  350.  
  351. procedure chat;
  352.  
  353.   var
  354.     count  : byte;
  355.     inch   : char;
  356.  
  357.   begin
  358.     inch := null;
  359.     clearsc;
  360.     lineout('Entering chat mode: CTL-C aborts at any time.');
  361.     lineout('Summoning Sysop...');
  362.     flush;
  363.     count := 1;
  364.     repeat
  365.       count := count + 1;
  366.       charout(bell);
  367.       delay(1000);
  368.       if inready then inch := charin(noecho);
  369.     until (count > 10) or (inch <> null);
  370.     while cts and (inch <> abort) do begin
  371.       inch := charin(echo);
  372.       if inch = cr then sendout(lf);
  373.     end;
  374.   end;
  375.  
  376. procedure newpass;
  377.  
  378.   var
  379.     temp   : name;
  380.     prompt : line;
  381.  
  382.   begin
  383.     repeat
  384.       prompt := 'Enter the password you want on this system: ';
  385.       password := allcaps(getinput(prompt, 14,noecho));
  386.       prompt := cr + lf + 'Enter it again, to be sure: ';
  387.       temp := allcaps(getinput(prompt, 14, noecho));
  388.     until (temp = password) or not cts;
  389.     lineout('New password is saved when the [G]oodbye command is executed.');
  390.   end;
  391.  
  392. procedure listusers;
  393.  
  394.   var
  395.     tempid: sysid;
  396.     inch:   name;
  397.  
  398.   begin
  399.     if cts then begin
  400.       clearsc;
  401.       reset(idfile);
  402.       repeat
  403.         read(idfile,tempid);
  404.         if access = 5 then begin
  405.           str(tempid.acc:1, inch);
  406.           stringout(inch + '  ');
  407.         end;
  408.         lineout(tempid.user);
  409.       until eof(idfile) or cancelled or not cts;
  410.       unload;
  411.     end;
  412.   end;
  413.  
  414. procedure userlog;
  415.  
  416.   var
  417.     call:   person;
  418.     loop:   integer;
  419.  
  420.   begin
  421.     if cts then begin
  422.       clearsc;
  423.       reset(logfile);
  424.       while cts and (not cancelled) and not eof(logfile) do begin
  425.         read(logfile,logrec);
  426.         if logrec.who < 1 then call := ('Not on userlist')
  427.           else call := getname(logrec.who);
  428.         if clockin then for loop := length(call)+1 to 25 do call := call+space;
  429.         stringout(call);
  430.         if clockin then stringout(logrec.when + ' to ' + logrec.done);
  431.         lineout(space);
  432.       end;
  433.       if access = 5 then begin
  434.         if getcap('Kill (Y/N)? ') = 'Y' then rewrite(logfile);
  435.       end;
  436.       close(logfile);
  437.       unload;
  438.     end;
  439.   end;
  440.  
  441. procedure sysoponly;
  442.  
  443.   var
  444.    inch : char;
  445.    number: integer;
  446.    temp: name;
  447.    comment: line;
  448.    comfile: file of line;
  449.  
  450.   begin
  451.     if cts then begin
  452.       clearsc;
  453.       assign(comfile, 'COMMENTS.BBS');
  454.       reset(comfile);
  455.       while cts and (not cancelled) and not eof(comfile) do begin
  456.         read(comfile,comment);
  457.         lineout(comment);
  458.       end;
  459.       if getcap('Kill (Y/N)? ') = 'Y' then rewrite(comfile);
  460.       close(comfile);
  461.       unload;
  462.     end;
  463.     repeat
  464.       number := getid('User name? ');
  465.       if number > 0 then begin
  466.         str(idrec.acc:2, temp);
  467.         lineout('Access:' + temp);
  468.         inch := getinput('New level? ', 1, echo);
  469.         if inch in ['0'..'5'] then idrec.acc := integer(inch) - integer('0');
  470.         reset(idfile);
  471.         seek(idfile, number - 1);
  472.         write(idfile, idrec);
  473.         unload;
  474.       end;
  475.     until number = 0;
  476.   end;
  477.  
  478. procedure menu;
  479.  
  480.   begin
  481.     if cts then begin
  482.       cancelled := false;
  483.       lineout(cr + lf + 'Information files:');
  484.       lineout('[H]elp...... user[L]og... [O]thersys.. [U]serlist.. [W]elcome... s[Y]sinfo...');
  485.       lineout(cr + lf + 'Message system:');
  486.       lineout('[E]nter..... [K]ill...... [R]ead...... [S]can...... [#]:Status..');
  487.       lineout(cr + lf + 'Functions:');
  488.       lineout('[C]hat...... [F]iles..... [G]oodbye... [I]nstall... [P]assword.. e[X]pert....');
  489.     end;
  490.   end;
  491.  
  492. procedure command;
  493.  
  494.   var
  495.     prompt: line;
  496.     inch  : char;
  497.     first : boolean;
  498.  
  499.   begin
  500.     first := true;
  501.     while cts do begin
  502.       if first and not expert then menu;
  503.       prompt := cr + lf + 'Command: ';
  504.       if not expert
  505.         then prompt := prompt + 'C,E,F,G,H,I,K,L,O,P,R,S,U,W,X,Y,# ? '
  506.         else prompt := prompt + '(? for menu) ? ';
  507.       flush;
  508.       inch := getcap(prompt);
  509.       first := true;
  510.       case inch of
  511.         'K': deletex;
  512.         'E': enter;
  513.         'R': receive;
  514.         'S': quickscan;
  515.         '#': begin status; showtime; connecttime; first := false; end;
  516.         'I': setvideo;
  517.         'F': filesys;
  518.         'G': disconnect;
  519.         'H': outfile('BBSHELP.TXT');
  520.         'Y': outfile('SYSINFO.TXT');
  521.         'W': outfile('WELCOME.TXT');
  522.         '?': if expert then menu;
  523.         'X': begin expert := not expert; first := false; end;
  524.         'C': chat;
  525.         'U': listusers;
  526.         'L': userlog;
  527.         'O': outfile('BBSLIST.TXT');
  528.         'P': newpass;
  529.         '@': if access=5 then sysoponly else first := false;
  530.         '!': if access=5 then printon := not printon else first := false;
  531.         else first := false;
  532.       end; {case}
  533.     end; {while cts}
  534.   end; {command}
  535.  
  536. procedure enterpass;
  537.  
  538.   var
  539.     temp:  name;
  540.     tries: byte;
  541.  
  542.   begin
  543.     tries := 0;
  544.     lineout(space);
  545.     repeat
  546.       if tries > 0 then stringout('Incorrect - try again: ');
  547.       tries := tries + 1;
  548.       temp := allcaps(getinput('Enter your password: ', 14, noecho));
  549.     until (temp = idrec.pass) or (tries = 3) or not cts;
  550.     if (temp <> idrec.pass) then hangup;
  551.   end;
  552.  
  553. procedure getdefaults;
  554.  
  555.   begin
  556.     enterpass;
  557.     if cts then begin
  558.       with idrec do begin
  559.         password := pass;
  560.         expert := (exfl = 0);
  561.         access := acc;
  562.         cs := clr;
  563.         bs := bsp;
  564.         lf := lnf;
  565.         caps := upc;
  566.         width := wid;
  567.         lastmess := lstm;
  568.         if clockin then lineout('Last on: ' + lsto);
  569.       end;
  570.     end;
  571.   end;
  572.  
  573. procedure newuser;
  574.  
  575.   begin
  576.     lineout(cr + lf + 'Getting new user password & terminal info:');
  577.     if cts then begin
  578.       newpass;
  579.       setvideo;
  580.       access := 1;
  581.     end;
  582.   end;
  583.  
  584. procedure signon(var caller: person);
  585.  
  586.   var ch: char;
  587.  
  588.   begin
  589.     ch := space;
  590.     repeat
  591.       repeat
  592.         caller := allcaps(getinput('What is your full name? ', 28, echo));
  593.       until (length(caller) > 4) or not cts;
  594.       if cts then begin
  595.         usernum := findid(caller);
  596.         if usernum=0 then ch:=getcap(caller + ': is this correct (Y/N)? ');
  597.       end;
  598.     until (usernum > 0) or (ch = 'Y') or not cts;
  599.     if cts then begin
  600.       if usernum = 0 then newuser else getdefaults;
  601.       dispcaller;
  602.       if access = 0 then begin
  603.         lineout('User ' + caller + ' has been denied system access.');
  604.         hangup;
  605.       end;
  606.     end;
  607.   end;
  608.  
  609. procedure logcall;
  610.  
  611.   begin
  612.     reset(logfile);
  613.     seek(logfile, filesize(logfile));
  614.     with logrec do begin
  615.       who := usernum;
  616.       if clockin then begin
  617.         when := timeon;
  618.         done := timeoff;
  619.       end;
  620.     end;
  621.     write(logfile, logrec);
  622.     close(logfile);
  623.   end;
  624.  
  625. procedure defaults;
  626.  
  627.   begin
  628.     lf := lnfd;
  629.     bl := null;
  630.     cs := lnfd;
  631.     bs := bksp;
  632.     expert := false;
  633.     caps := false;
  634.     width := 80;
  635.     access := 1;
  636.     assign(idfile, 'IDS.BBS');
  637.     assign(logfile, 'LOG.BBS');
  638.     lastmess := 0;
  639.     caller := space;
  640.     usernum := 0;
  641.     messopen := false;
  642.     filesopen := false;
  643.     printon := false;
  644.     inbuffer := '';
  645.     cancelled := false;
  646.     controls := false;
  647.   end;
  648.  
  649. begin
  650.   exitchar := space;
  651.   local := false;
  652.   resetbuff;
  653.   setup;
  654.   defaults;
  655.   awaitcall;
  656.   repeat
  657.     if clockin then begin
  658.       clock(onmonth, ondate, onhour, onmin, onsec);
  659.       timeon := time(onmonth, ondate, onhour, onmin, onsec);
  660.       showtime;
  661.     end;
  662.     flush;
  663.     if cts then outfile('WELCOME.TXT');
  664.     if cts then signon(caller);
  665.     if cts then initmess;
  666.     if cts and (usernum > 0) then begin
  667.       lineout('Checking for mail...');
  668.       messagesearch(1,0,usernum,0);
  669.     end;
  670.     if cts then command;
  671.     writeln('hung up...');
  672.     if clockin then begin
  673.       clock(offmonth, offdate, offhour, offmin, offsec);
  674.       timeoff := time(offmonth, offdate, offhour, offmin, offsec);
  675.     end;
  676.     logcall;
  677.     if messopen then closemess;
  678.     close(idfile);
  679.     unload;
  680.     defaults;
  681.     awaitcall;
  682.   until exitchar = abort;
  683. end.
  684. əəəəəəə