home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 276.img / FORUM21S.ZIP / MAINMENU.PAS < prev    next >
Pascal/Delphi Source File  |  1988-02-15  |  25KB  |  1,084 lines

  1. {$R-,S-,I-,D-,T-,F-,V-,B-,N-,L+ }
  2. {$M 65500,0,0 }
  3.  
  4. unit mainmenu;
  5.  
  6. interface
  7.  
  8. uses crt,dos,
  9.      gentypes,configrt,statret,textret,userret,mailret,
  10.      gensubs,subs1,subs2,windows,
  11.      chatstuf,mainr1,mainr2,overret1;
  12.  
  13. procedure editusers;
  14. procedure zapspecifiedusers;
  15. procedure summonsysop;
  16. procedure offtheforum;
  17. procedure listusers;
  18. procedure transfername;
  19. procedure editnews;
  20. procedure yourstatus;
  21. procedure delerrlog;
  22. procedure feedback;
  23. procedure settime;
  24. procedure changepwd;
  25. procedure requestraise;
  26. procedure makeuser;
  27. procedure infoformhunt;
  28. procedure donations;
  29. procedure viewsyslog;
  30. procedure delsyslog;
  31. procedure showsystemstatus;
  32. procedure showallforms;
  33. procedure showallsysops;
  34. procedure mainhelp;
  35. procedure otherbbs;
  36. procedure readerrlog;
  37. procedure showad;
  38. procedure setlastcall;
  39. procedure removeallforms;
  40. procedure readfeedback;
  41.  
  42. implementation
  43.  
  44. procedure editusers;
  45. var eunum:integer;
  46.     matched:boolean;
  47.  
  48.   procedure elistusers (getspecs:boolean);
  49.   var cnt,f,l:integer;
  50.       u:userrec;
  51.       us:userspecsrec;
  52.  
  53.     procedure listuser;
  54.     begin
  55.       write (cnt:4,' ');
  56.       tab (u.handle,31);
  57.       write (u.level:6,' ');
  58.       tab (datestr(u.laston),8);
  59.       writeln (u.nbu:6,u.numon:6,postcallratio(u):7:2)
  60.     end;
  61.  
  62.   begin
  63.     if getspecs
  64.       then if selectspecs(us)
  65.         then exit
  66.         else
  67.           begin
  68.             f:=1;
  69.             l:=numusers
  70.           end
  71.       else parserange (numusers,f,l);
  72.     seek (ufile,f);
  73.     matched:=false;
  74.     writeln (^B^M^M' Num Name                            Level ',
  75.              'Last on  Posts Calls PCR');
  76.     for cnt:=f to l do begin
  77.       read (ufile,u);
  78.       if (not getspecs) or fitsspecs(u,us) then begin
  79.         listuser;
  80.         matched:=true
  81.       end;
  82.       handleincoming;
  83.       if break then exit
  84.     end;
  85.     if not matched then
  86.       if getspecs
  87.         then writeln (^B^M'No users match specifications!')
  88.         else writeln (^B^M'No users found in that range!')
  89.   end;
  90.  
  91. begin
  92.   repeat
  93.     writestr (^M'User to edit [?,??=list]:');
  94.     if (length(input)=0) or (match(input,'Q')) then exit;
  95.     if input[1]='?'
  96.       then elistusers (input='??')
  97.       else begin
  98.         eunum:=lookupuser (input);
  99.         if eunum=0
  100.           then writestr ('User not found!')
  101.           else edituser (eunum)
  102.       end
  103.   until hungupon
  104. end;
  105.  
  106. procedure zapspecifiedusers;
  107. var us:userspecsrec;
  108.     confirm:boolean;
  109.     u:userrec;
  110.     cnt:integer;
  111.     done:boolean;
  112. begin
  113.   if selectspecs (us) then exit;
  114.   writestr ('Confirm each deletion individually? *');
  115.   if length(input)=0 then exit;
  116.   confirm:=yes;
  117.   if not confirm then begin
  118.     writestr (^M'Are you SURE you want to mass delete without confirmation? *');
  119.     if not yes then exit
  120.   end;
  121.   for cnt:=1 to numusers do begin
  122.     seek (ufile,cnt);
  123.     read (ufile,u);
  124.     if (length(u.handle)>0) and fitsspecs (u,us) then begin
  125.       if confirm
  126.         then
  127.           begin
  128.             done:=false;
  129.             repeat
  130.               writestr ('Delete '+u.handle+' (Y/N/X/E):');
  131.               if length(input)>0 then case upcase(input[1]) of
  132.                 'Y':begin
  133.                       done:=true;
  134.                       writeln ('Deleting '+u.handle+'...');
  135.                       deleteuser (cnt)
  136.                     end;
  137.                 'N':done:=true;
  138.                 'X':exit;
  139.                 'E':begin
  140.                       edituser(cnt);
  141.                       writeln;
  142.                       writeln
  143.                     end
  144.               end
  145.             until done
  146.           end
  147.         else
  148.           begin
  149.             writeln ('Deleting '+u.handle+'...');
  150.             if break then begin
  151.               writestr ('Aborted!!');
  152.               exit
  153.             end;
  154.             deleteuser (cnt)
  155.           end
  156.     end
  157.   end
  158. end;
  159.  
  160. procedure summonsysop;
  161. var tf:text;
  162.     k:char;
  163. begin
  164.   chatmode:=not chatmode;
  165.   bottomline;
  166.   if chatmode
  167.     then
  168.       if sysopisavail
  169.         then
  170.           begin
  171.             writestr ('Enter a short reason: &');
  172.             chatreason:=input;
  173.             if length(input)=0 then begin
  174.               chatmode:=false;
  175.               exit
  176.             end;
  177.             writelog (1,3,chatreason);
  178.             splitscreen (4);
  179.             top;
  180.             clrscr;
  181.             writeln (usr,unam,' wants to chat!  His reason:');
  182.             write (usr,chatreason);
  183.             bottom;
  184.             assign (tf,textfiledir+'Summon');
  185.             reset (tf);
  186.             if ioresult=0 then begin
  187.               while (not (eof(tf) or hungupon)) and chatmode do
  188.                 begin
  189.                   read (tf,k);
  190.                   nobreak:=true;
  191.                   if ord(k)=7 then summonbeep else writechar (k);
  192.                   if keyhit then begin
  193.                     k:=bioskey;
  194.                     clearbreak;
  195.                     chat (false)
  196.                   end
  197.                 end;
  198.               textclose (tf)
  199.             end;
  200.             if chatmode
  201.               then writestr (^M'Use [C] again to turn off page.')
  202.               else unsplit
  203.           end
  204.         else
  205.           begin
  206.             writestr ('Sorry, '+sysopname+
  207.                       ' isn''t available right now!');
  208.             chatmode:=false;
  209.             writelog (1,2,'')
  210.           end
  211.     else writestr ('Page off.  Use [C] to turn it back on.');
  212.   clearbreak
  213. end;
  214.  
  215. procedure offtheforum;
  216. var q,n:integer;
  217.     tn:file of integer;
  218.     m:message;
  219. begin
  220.   writestr ('Hang up now? *');
  221.   if yes then begin
  222.     writestr ('Leave message to next user? *');
  223.     if yes then begin
  224.       q:=editor(m,false);
  225.       if q>=0 then begin
  226.         if tonext>=0 then deletetext (tonext);
  227.         tonext:=q;
  228.         writestatus
  229.       end
  230.     end;
  231.     printfile (textfiledir+'GoodBye');
  232.     disconnect
  233.   end
  234. end;
  235.  
  236. procedure listusers;
  237. var cnt:integer;
  238.     u:userrec;
  239. begin
  240.   writeln (^B'Name                             Level'^M);
  241.   if break then exit;
  242.   for cnt:=1 to numusers do
  243.     begin
  244.       seek (ufile,cnt);
  245.       read (ufile,u); che;
  246.       if length(u.handle)>0 then begin
  247.         tab (u.handle,33);
  248.         if break then exit;
  249.         writestr (strr(u.level));
  250.         if break then exit
  251.       end
  252.     end
  253. end;
  254.  
  255. procedure transfername;
  256. var un,nlvl,ntime,tmp:integer;
  257.     u:userrec;
  258. begin
  259.   if tempsysop then begin
  260.     writestr ('Disabling temporary sysop powers...');
  261.     ulvl:=regularlevel;
  262.     tempsysop:=false
  263.   end;
  264.   writestr ('Transfer to user name:');
  265.   if length(input)=0 then exit;
  266.   un:=lookupuser(input);
  267.   if unum=un then begin
  268.     writestr ('You can''t transfer to yourself!');
  269.     exit
  270.   end;
  271.   if un=0 then begin
  272.     writestr ('No such user.');
  273.     exit
  274.   end;
  275.   seek (ufile,un);
  276.   read (ufile,u);
  277.   if ulvl<sysoplevel then if not checkpassword(u) then begin
  278.     writelog (1,5,u.handle);
  279.     exit
  280.   end;
  281.   writelog (1,4,u.handle);
  282.   updateuserstats (false);
  283.   ntime:=0;
  284.   if datepart(u.laston)<>datepart(now) then begin
  285.     tmp:=ulvl;
  286.     if tmp<1 then tmp:=1;
  287.     if tmp>100 then tmp:=100;
  288.     ntime:=usertime[tmp]
  289.   end;
  290.   if u.timetoday<10
  291.     then if issysop or (u.level>=sysoplevel)
  292.       then
  293.         begin
  294.           writestr ('The user has '+strr(u.timetoday)+' min(s) left!');
  295.           writestr ('New time left:');
  296.           ntime:=valu(input)
  297.         end
  298.       else
  299.         if u.timetoday>0
  300.           then writeln ('Warning: You have ',u.timetoday,' minutes left!')
  301.           else
  302.             begin
  303.               writestr ('Sorry, that user doesn''t have any time left!');
  304.               exit
  305.             end;
  306.   unum:=un;
  307.   readurec;
  308.   if ntime<>0 then begin
  309.     urec.timetoday:=ntime;
  310.     writeurec
  311.   end;
  312. end;
  313.  
  314. procedure editnews;
  315. var nn,numnews:integer;
  316.     nf:file of integer;
  317.  
  318.   procedure getnn (txt:mstr);
  319.   begin
  320.     writestr ('News number to '+txt+':');
  321.     nn:=valu(input);
  322.     if (nn<1) or (nn>numnews) then nn:=0
  323.   end;
  324.  
  325.   procedure delnews;
  326.   var cnt:integer;
  327.       r:integer;
  328.   begin
  329.     if nn=0 then getnn ('delete');
  330.     if nn<>0 then begin
  331.       seek (nf,nn-1);
  332.       read (nf,r); che;
  333.       deletetext (r);
  334.       numnews:=filesize(nf)-1;
  335.       for cnt:=nn to numnews do
  336.         begin
  337.           seek (nf,cnt);
  338.           read (nf,r);
  339.           seek (nf,cnt-1);
  340.           write (nf,r)
  341.         end;
  342.       seek (nf,numnews);
  343.       truncate (nf)
  344.     end
  345.   end;
  346.  
  347.   procedure listnews;
  348.   var cnt:integer;
  349.       r,sector:integer;
  350.       q:buffer;
  351.       l:anystr;
  352.       k:char;
  353.   begin
  354.     clearbreak;
  355.     for cnt:=1 to numnews do begin
  356.       seek (nf,cnt-1);
  357.       read (nf,r);
  358.       seek (tfile,r);
  359.       read (tfile,q);
  360.       write (strr(cnt)+'. ');
  361.       r:=1;
  362.       k:=' ';
  363.       l:='';
  364.       while (ord(k)<>13) and not hungupon do begin
  365.         k:=q[r];
  366.         r:=r+1;
  367.         if (k=#0) or (r>sectorsize) then k:=chr(13);
  368.         l:=l+k
  369.       end;
  370.       writeln (l);
  371.       if break then exit
  372.     end;
  373.     writeln
  374.   end;
  375.  
  376.   procedure viewnews;
  377.   var r:integer;
  378.   begin
  379.     if nn=0 then getnn ('view');
  380.     if nn<>0 then begin
  381.       seek (nf,nn-1);
  382.       read (nf,r); che;
  383.       printtext (r)
  384.     end
  385.   end;
  386.  
  387.   procedure adddnews;
  388.   begin
  389.     close (nf);
  390.     addnews;
  391.     assign (nf,'News');
  392.     reset (nf)
  393.   end;
  394.  
  395. var q:integer;
  396. begin
  397.   assign (nf,'News');
  398.   reset (nf);
  399.   if ioresult<>0 then writestr ('No news!  Use [A] to add some!') else begin
  400.     repeat
  401.       numnews:=filesize(nf);
  402.       write (^B^M'News entries: ',numnews);
  403.       q:=menu ('News edit','NEWS','ADLVQ');
  404.       nn:=valu(copy(input,2,255));
  405.       if (nn<1) or (nn>numnews) then nn:=0;
  406.       case q of
  407.         1:adddnews;
  408.         2:delnews;
  409.         3:listnews;
  410.         4:viewnews
  411.       end;
  412.       if numnews=0 then begin
  413.         close (nf);
  414.         erase (nf);
  415.         writestr ('No more news!  Use [A] to add some.');
  416.         q:=5
  417.       end
  418.     until (q=5) or hungupon
  419.   end;
  420.   close (nf)
  421. end;
  422.  
  423. procedure yourstatus;
  424. begin
  425.   writehdr ('Your Status');
  426.   writeln ('Name:   '^S,unam,
  427.          ^M'Level:  '^S,ulvl,
  428.          ^M'Calls:  '^S,urec.numon,
  429.          ^M'Posted: '^S,urec.nbu,
  430.        ^M^M'Ascii',
  431.          ^M'  Uploads:     '^S,urec.nup,
  432.          ^M'  Downloads:   '^S,urec.ndn,
  433.          ^M'XMODEM',
  434.          ^M'  Uploads:     '^S,urec.uploads,
  435.          ^M'  Downloads:   '^S,urec.downloads,
  436.        ^M^M'Total time on: '^S,urec.totaltime:0:0,
  437.          ^M'Time left:     '^S,timeleft)
  438. end;
  439.  
  440. procedure delerrlog;
  441. var e:text;
  442.     i:integer;
  443. begin
  444.   writestr ('Delete error log:  Confirm:');
  445.   if not yes then exit;
  446.   assign (e,'errlog');
  447.   reset (e);
  448.   i:=ioresult;
  449.   if ioresult=1
  450.     then writeln (^M'No error log!')
  451.     else begin
  452.       textclose (e);
  453.       erase (e);
  454.       writestr ('Error log deleted.');
  455.       if ioresult>1
  456.         then writeln ('I/O error ',i,' deleting error log!');
  457.       writelog (2,2,'')
  458.     end
  459. end;
  460.  
  461. procedure feedback;
  462. var m:mailrec;
  463.     me:message;
  464. begin
  465.   writestr ('Leave feedback? *');
  466.   if not yes then exit;
  467.   m.line:=editor(me,true);
  468.   if m.line<0 then exit;
  469.   m.title:=me.title;
  470.   m.sentby:=unam;
  471.   m.anon:=false;
  472.   m.when:=now;
  473.   addfeedback (m);
  474.   writestr ('Feedback sent.')
  475. end;
  476.  
  477. procedure settime;
  478. var t:integer;
  479.     n:longint;
  480.     r:registers;
  481.     d:datetime;
  482. begin
  483.   writestr ('Current time: '+timestr(now));
  484.   writestr ('Current date: '+datestr(now));
  485.   writestr ('Enter new time:');
  486.   if length(input)<>0
  487.     then begin
  488.       t:=timeleft;
  489.       unpacktime (timeval(input),d);
  490.       r.ch:=d.hour;
  491.       r.cl:=d.min;
  492.       r.dh:=0;
  493.       r.dl:=0;
  494.       r.ah:=$2d;
  495.       intr ($21,r);
  496.       if r.al=$ff then writestr ('Invalid time!');
  497.       settimeleft (t)
  498.     end;
  499.   writestr ('Enter new date:');
  500.   if length(input)<>0
  501.     then begin
  502.       unpacktime (dateval(input),d);
  503.       r.dl:=d.day;
  504.       r.dh:=d.month;
  505.       r.cx:=d.year;
  506.       r.ah:=$2b;
  507.       intr ($21,r);
  508.       if r.al=$ff then writestr ('Invalid date!')
  509.     end;
  510.   writelog (2,4,'')
  511. end;
  512.  
  513. procedure changepwd;
  514. var t:sstr;
  515. begin
  516.   writehdr ('Password Change');
  517.   dots:=true;
  518.   buflen:=15;
  519.   write ('Enter new password: ');
  520.   if getpassword
  521.     then begin
  522.       writeurec;
  523.       writestr ('Password changed.');
  524.       writelog (1,1,'')
  525.     end else
  526.       writestr ('No change.')
  527. end;
  528.  
  529. procedure requestraise;
  530. var t:text;
  531.     q:lstr;
  532.     p,l1,l2:integer;
  533.     s1,s2:sstr;
  534.     me:message;
  535.     m:mailrec;
  536. label nope,found;
  537. begin
  538.   assign (t,textfiledir+'RAISEREQ');
  539.   reset (t);
  540.   if ioresult<>0 then goto nope;
  541.   printtexttopoint (t);
  542.   while not eof(t) do begin
  543.     readln (t,q);
  544.     p:=pos('-',q);
  545.     if p>0
  546.       then
  547.         begin
  548.           s1:=copy(q,1,p-1);
  549.           s2:=copy(q,p+1,255)
  550.         end
  551.       else
  552.         begin
  553.           s1:=copy(q,1,15);
  554.           s2:=s1
  555.         end;
  556.     val (s1,l1,p);
  557.     if p=0 then val (s2,l2,p);
  558.     if p<>0 then begin
  559.       textclose (t);
  560.       error ('Invalid range in RAISEREQ: %1','',q);
  561.       exit
  562.     end;
  563.     if (ulvl>=l1) and (ulvl<=l2) then goto found;
  564.     skiptopoint (t)
  565.   end;
  566.   nope:
  567.   error ('No text for level %1','',strr(ulvl));
  568.   textclose (t);
  569.   p:=ioresult;
  570.   exit;
  571.   found:
  572.   printtexttopoint (t);
  573.   textclose (t);
  574.   if hungupon then exit;
  575.   m.line:=editor (me,false);
  576.   if m.line<0 then exit;
  577.   m.anon:=false;
  578.   m.title:='Raise request; now lvl='+strr(ulvl);
  579.   m.sentby:=unam;
  580.   m.when:=now;
  581.   addfeedback (m);
  582. end;
  583.  
  584. procedure makeuser;
  585. var u:userrec;
  586.     un,ln:integer;
  587. begin
  588.   writehdr ('Add a user');
  589.   writestr ('Name:');
  590.   if length(input)=0 then exit;
  591.   if lookupuser(input)<>0 then begin
  592.     writestr ('Sorry!  Already exists!');
  593.     exit
  594.   end;
  595.   u.handle:=input;
  596.   writestr ('Password:');
  597.   u.password:=input;
  598.   writestr ('Level:');
  599.   if length(input)=0 then exit;
  600.   u.level:=valu(input);
  601.   un:=adduser(u);
  602.   if un=-1 then begin
  603.     writestr ('Sorry, no room for new users!');
  604.     exit
  605.   end;
  606.   ln:=u.level;
  607.   if ln<1 then ln:=1;
  608.   if ln>100 then ln:=100;
  609.   u.timetoday:=usertime[ln];
  610.   writeufile (u,un);
  611.   writestr ('User added as #'+strr(un)+'.');
  612.   writelog (2,8,u.handle)
  613. end;
  614.  
  615. procedure infoformhunt;
  616. begin
  617.   writestr ('User to search for [CR=all users]:');
  618.   writeln (^M);
  619.   showinfoforms (input)
  620. end;
  621.  
  622. procedure donations;
  623. var fn:lstr;
  624. begin
  625.   fn:=textfiledir+'Donation';
  626.   if exist (fn)
  627.     then printfile (fn)
  628.     else begin
  629.       writestr ('I''m sorry, no information is currently available.');
  630.       if issysop
  631.         then writestr (
  632. 'Sysop:  To create donation information text, make a file called '+fn)
  633.     end
  634. end;
  635.  
  636. procedure viewsyslog;
  637. var n:integer;
  638.     l:logrec;
  639.  
  640.   function lookupsyslogdat (m,s:integer):integer;
  641.   var cnt:integer;
  642.   begin
  643.     for cnt:=1 to numsyslogdat do with syslogdat[cnt] do
  644.       if (menu=m) and (subcommand=s) then begin
  645.         lookupsyslogdat:=cnt;
  646.         exit
  647.       end;
  648.     lookupsyslogdat:=0
  649.   end;
  650.  
  651.   function firstentry:boolean;
  652.   begin
  653.     firstentry:=(l.menu=0) and (l.subcommand in [1..2])
  654.   end;
  655.  
  656.   procedure backup;
  657.   begin
  658.     while n<>0 do begin
  659.       n:=n-1;
  660.       seek (logfile,n);
  661.       read (logfile,l);
  662.       if firstentry then exit
  663.     end;
  664.     n:=-1
  665.   end;
  666.  
  667.   procedure showentry (includedate:boolean);
  668.   var q:lstr;
  669.       p:integer;
  670.   begin
  671.     q:=syslogdat[lookupsyslogdat(l.menu,l.subcommand)].text;
  672.     p:=pos('%',q);
  673.     if p<>0 then q:=copy(q,1,p-1)+l.param+copy(q,p+1,255);
  674.     if includedate then q:=q+' on '+datestr(l.when);
  675.     q:=q+' at '+timestr(l.when);
  676.     writeln (q)
  677.   end;
  678.  
  679. var b:boolean;
  680. begin
  681.   writehdr ('View system log');
  682.   writeln ('Press space to advance to the previous caller, X to abort.');
  683.   writeln;
  684.   writelog (2,6,'');
  685.   n:=filesize(logfile);
  686.   repeat
  687.     clearbreak;
  688.     writeln (^M);
  689.     backup;
  690.     if n=-1 then exit;
  691.     seek (logfile,n);
  692.     read (logfile,l);
  693.     showentry (true);
  694.     b:=false;
  695.     while not (eof(logfile) or break or xpressed or b) do begin
  696.       read (logfile,l);
  697.       b:=firstentry;
  698.       if not b then showentry (false);
  699.     end
  700.   until xpressed
  701. end;
  702.  
  703. procedure delsyslog;
  704. begin
  705.   writestr ('Delete system log: Confirm:');
  706.   if not yes then exit;
  707.   close (logfile);
  708.   rewrite (logfile);
  709.   writeln (^M'System log deleted.');
  710.   writelog (2,7,unam)
  711. end;
  712.  
  713. procedure showsystemstatus;
  714. var totalused,totalidle,totalup,totaldown,totalmins,callsday:real;
  715.  
  716.   procedure percent (prompt:mstr; top,bot:real);
  717.   var p:real;
  718.   begin
  719.     write (prompt);
  720.     if bot<1 then begin
  721.       writeln ('N/A');
  722.       exit
  723.     end;
  724.     p:=round(1000*top/bot)/10;
  725.     writeln (p:0:1,'%')
  726.   end;
  727.  
  728. begin
  729.   totalused:=numminsused.total+elapsedtime(numminsused);
  730.   totalidle:=numminsidle.total;
  731.   totalup:=totalidle+numminsused.total;
  732.   totalmins:=1440.0*(numdaysup-1.0)+timer;
  733.   totaldown:=totalmins-totalup;
  734.   callsday:=round(10*numcallers/numdaysup)/10;
  735.   writehdr ('System Status');
  736.   writeln ('Time & date:       '^S,timestr(now),', ',datestr(now),
  737.        ^M^J'Calls today:       '^S,callstoday,
  738.        ^M^J'Total callers:     '^S,numcallers:0:0,
  739.        ^M^J'Total days up:     '^S,numdaysup,
  740.        ^M^J'Calls per day:     '^S,callsday:0:1,
  741.        ^M^J'Total mins in use: '^S,numminsused.total:0:0,
  742.        ^M^J'Total mins idle:   '^S,totalidle:0:0,
  743.        ^M^J'Mins file xfer:    '^S,numminsxfer.total:0:0,
  744.        ^M^J'Total mins up:     '^S,totalup:0:0,
  745.        ^M^J'Total mins down:   '^S,totaldown:0:0);
  746.   percent ('Percent in use:    '^S,totalused,totalmins);
  747.   percent ('Percent idle:      '^S,totalidle,totalmins);
  748.   percent ('Percent up:        '^S,totalup,totalmins);
  749.   percent ('Percent down:      '^S,totaldown,totalmins);
  750. end;
  751.  
  752. procedure showallforms;
  753. begin
  754.   showinfoforms ('')
  755. end;
  756.  
  757. procedure showallsysops;
  758. var n:integer;
  759.     u:userrec;
  760.     q:set of configtype;
  761.     s:configtype;
  762.  
  763.   procedure showuser;
  764.   const sectionnames:array [udsysop..databasesysop] of string[20]=
  765.          ('File transfer','Bulletin section','Voting booths',
  766.           'E-mail section','Doors','Main menu','Databases');
  767.   var s:configtype;
  768.   begin
  769.     writeln (^B^M'Name:  '^S,u.handle,
  770.                ^M'Level: '^S,u.level,^M);
  771.     for s:=udsysop to databasesysop do
  772.       if s in u.config then
  773.         writeln ('Sysop of the ',sectionnames[s]);
  774.     writestr (^M'Edit user? *');
  775.     if yes then edituser (n)
  776.   end;
  777.  
  778. begin
  779.   q:=[];
  780.   for s:=udsysop to databasesysop do q:=q+[s];
  781.   for n:=1 to numusers do begin
  782.     seek (ufile,n);
  783.     read (ufile,u);
  784.     if (u.level>=sysoplevel) or (q*u.config<>[]) then showuser
  785.   end
  786. end;
  787.  
  788. procedure mainhelp;
  789. begin
  790.   help ('Mainmenu.hlp')
  791. end;
  792.  
  793. procedure otherbbs;
  794. begin
  795.   printfile (textfiledir+'Otherbbs')
  796. end;
  797.  
  798. procedure readerrlog;
  799. begin
  800.   if exist ('Errlog')
  801.     then printfile ('Errlog')
  802.     else writestr ('No error file!')
  803. end;
  804.  
  805. procedure showad;
  806. var fn:lstr;
  807. begin
  808.   fn:=textfiledir+'Forum.AD';
  809.   if exist (fn) then printfile (fn)
  810. end;
  811.  
  812. procedure setlastcall;
  813.  
  814.   function digit (k:char):boolean;
  815.   begin
  816.     digit:=ord(k) in [48..57]
  817.   end;
  818.  
  819.   function validtime (inp:sstr):boolean;
  820.   var c,s,l:integer;
  821.       d1,d2,d3,d4:char;
  822.       ap,m:char;
  823.   begin
  824.     validtime:=false;
  825.     l:=length(inp);
  826.     if (l<7) or (l>8) then exit;
  827.     c:=pos(':',inp);
  828.     if c<>l-5 then exit;
  829.     s:=pos(' ',inp);
  830.     if s<>l-2 then exit;
  831.     d2:=inp[c-1];
  832.     if l=7
  833.       then d1:='0'
  834.       else d1:=inp[1];
  835.     d3:=inp[c+1];
  836.     d4:=inp[c+2];
  837.     ap:=upcase(inp[s+1]);
  838.     m:=upcase(inp[s+2]);
  839.     if d1='1' then if d2>'2' then d2:='!';
  840.     if (d1>='0') and (d1<='1') and digit(d2) and (d3>='0') and (d3<='5')
  841.        and digit(d4) and ((ap='A') or (ap='P')) and (m='M')
  842.          then validtime:=true
  843.   end;
  844.  
  845.   function validdate (inp:sstr):boolean;
  846.   var k,l:char;
  847.  
  848.     function gchar:char;
  849.     begin
  850.       if length(inp)=0 then begin
  851.         gchar:='?';
  852.         exit
  853.       end;
  854.       gchar:=inp[1];
  855.       delete (inp,1,1)
  856.     end;
  857.  
  858.   begin
  859.     validdate:=false;
  860.     k:=gchar;
  861.     l:=gchar;
  862.     if not digit(k) then exit;
  863.     if l='/'
  864.       then if k='0'
  865.         then exit
  866.         else
  867.       else begin
  868.         if k>'1' then exit;
  869.         if not digit(l) then exit;
  870.         if (l>'2') and (k='1') then exit;
  871.         l:=gchar;
  872.         if l<>'/' then exit
  873.       end;
  874.     k:=gchar;
  875.     l:=gchar;
  876.     if l='/'
  877.       then if k='0'
  878.         then exit
  879.         else
  880.       else begin
  881.         if k>'3' then exit;
  882.         if not digit(l) then exit;
  883.         if (k='3') and (l>'1') then exit;
  884.         l:=gchar;
  885.         if l<>'/' then exit
  886.       end;
  887.     if digit(gchar) and digit(gchar) then validdate:=true
  888.   end;
  889.  
  890. begin
  891.   writeln (^M'Your last call was: '^S,datestr(laston),' at ',timestr(laston));
  892.   writestr (^M'Enter new date (mm/dd/yy):');
  893.   if length(input)>0
  894.     then if validdate (input)
  895.       then laston:=dateval(input)+timepart(laston)
  896.       else writestr ('Invalid date!');
  897.   writestr (^M'Enter new time (hh:mm am/pm):');
  898.   if length(input)>0
  899.     then if validtime(input)
  900.       then laston:=timeval(input)+datepart(laston)
  901.       else writestr ('Invalid time!')
  902. end;
  903.  
  904. procedure removeallforms;
  905. var cnt,ndel:integer;
  906.     u:userrec;
  907. begin
  908.   writestr ('Erase ALL info-forms:  Are you sure? *');
  909.   if not yes then exit;
  910.   writeurec;
  911.   writestr (^M'Erasing... please stand by...');
  912.   ndel:=0;
  913.   for cnt:=1 to numusers do begin
  914.     if (cnt mod 10)=0 then write (cnt,', ');
  915.     seek (ufile,cnt);
  916.     read (ufile,u);
  917.     if u.infoform>=0 then begin
  918.       deletetext (u.infoform);
  919.       u.infoform:=-1;
  920.       seek (ufile,cnt);
  921.       write (ufile,u);
  922.       ndel:=ndel+1
  923.     end
  924.   end;
  925.   writeln ('done.');
  926.   writestr (^M'All '+strr(ndel)+' forms erased.');
  927.   readurec
  928. end;
  929.  
  930. procedure readfeedback;
  931. var ffile:file of mailrec;
  932.     m:mailrec;
  933.     me:message;
  934.     cur:integer;
  935.  
  936.   function nummessages:integer;
  937.   begin
  938.     nummessages:=filesize(ffile)
  939.   end;
  940.  
  941.   function checkcur:boolean;
  942.   begin
  943.     if length(input)>1 then cur:=valu(copy(input,2,255));
  944.     if (cur<1) or (cur>nummessages) then begin
  945.       writestr (^M'Message out of range!');
  946.       cur:=0;
  947.       checkcur:=true
  948.     end else begin
  949.       checkcur:=false;
  950.       seek (ffile,cur-1);
  951.       read (ffile,m)
  952.     end
  953.   end;
  954.  
  955.   procedure readnum (n:integer);
  956.   begin
  957.     cur:=n;
  958.     input:='';
  959.     if checkcur then exit;
  960.     writeln (^B^M'Message: '^S,cur,
  961.                ^M'Title:   '^S,m.title,
  962.                ^M'Sent by: '^S,m.sentby,
  963.                ^M'Sent on: '^S,datestr(m.when),' at ',timestr(m.when),^M);
  964.     if break then exit;
  965.     printtext (m.line)
  966.   end;
  967.  
  968.   procedure writecurmsg;
  969.   begin
  970.     if (cur<1) or (cur>nummessages) then cur:=0;
  971.     write (^B^M'Current msg: '^S);
  972.     if cur=0 then write ('None') else begin
  973.       seek (ffile,cur-1);
  974.       read (ffile,m);
  975.       write (m.title,' by ',m.sentby)
  976.     end
  977.   end;
  978.  
  979.   procedure delfeedback;
  980.   var cnt:integer;
  981.   begin
  982.     if checkcur then exit;
  983.     deletetext (m.line);
  984.     for cnt:=cur to nummessages-1 do begin
  985.       seek (ffile,cnt);
  986.       read (ffile,m);
  987.       seek (ffile,cnt-1);
  988.       write (ffile,m)
  989.     end;
  990.     seek (ffile,nummessages-1);
  991.     truncate (ffile);
  992.     cur:=cur-1
  993.   end;
  994.  
  995.   procedure editusr;
  996.   var n:integer;
  997.   begin
  998.     if checkcur then exit;
  999.     n:=lookupuser (m.sentby);
  1000.     if n=0
  1001.       then writestr ('User disappeared!')
  1002.       else edituser (n)
  1003.   end;
  1004.  
  1005.   procedure infoform;
  1006.   begin
  1007.     if checkcur then exit;
  1008.     showinfoforms (m.sentby)
  1009.   end;
  1010.  
  1011.   procedure nextfeedback;
  1012.   begin
  1013.     cur:=cur+1;
  1014.     if cur>nummessages then begin
  1015.       writestr (^M'Sorry, no more feedback!');
  1016.       cur:=0;
  1017.       exit
  1018.     end;
  1019.     readnum (cur)
  1020.   end;
  1021.  
  1022.   procedure readagain;
  1023.   begin
  1024.     if checkcur then exit;
  1025.     readnum (cur)
  1026.   end;
  1027.  
  1028.   procedure replyfeedback;
  1029.   begin
  1030.     if checkcur then exit;
  1031.     sendmailto (m.sentby,false)
  1032.   end;
  1033.  
  1034.   procedure listfeedback;
  1035.   var cnt:integer;
  1036.   begin
  1037.     if nummessages=0 then exit;
  1038.     thereare (nummessages,'piece of feedback','pieces of feedback');
  1039.     if break then exit;
  1040.     writeln (^M'Num Title                          Left by'^M);
  1041.     seek (ffile,0);
  1042.     for cnt:=1 to nummessages do begin
  1043.       read (ffile,m);
  1044.       tab (strr(cnt),4);
  1045.       if break then exit;
  1046.       tab (m.title,31);
  1047.       writeln (m.sentby);
  1048.       if break then exit
  1049.     end
  1050.   end;
  1051.  
  1052. var q:integer;
  1053. label exit;
  1054. begin
  1055.   assign (ffile,'Feedback');
  1056.   reset (ffile);
  1057.   if ioresult<>0 then rewrite (ffile);
  1058.   cur:=0;
  1059.   repeat
  1060.     if nummessages=0 then begin
  1061.       writestr ('Sorry, no feedback!');
  1062.       goto exit
  1063.     end;
  1064.     writecurmsg;
  1065.     q:=menu ('Feedback','FEED','Q#DEIR_AL');
  1066.     if q<0
  1067.       then readnum (-q)
  1068.       else case q of
  1069.         3:delfeedback;
  1070.         4:editusr;
  1071.         5:infoform;
  1072.         6:replyfeedback;
  1073.         7:nextfeedback;
  1074.         8:readagain;
  1075.         9:listfeedback;
  1076.       end
  1077.   until (q=1) or hungupon;
  1078.   exit:
  1079.   close (ffile)
  1080. end;
  1081.  
  1082. begin
  1083. end.
  1084.