home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 189.img / TCS120S.ZIP / EMAIL.PAS < prev    next >
Pascal/Delphi Source File  |  1989-04-04  |  28KB  |  1,128 lines

  1. {$R-,S-,I-,D-,F+,V-,B-,N-,O+ }
  2. {$M 65500,0,0 }
  3.  
  4. unit email;
  5.  
  6. interface
  7.  
  8. uses gentypes,configrt,gensubs,subs1,subs2,textret,flags,
  9.      mailret,userret,overret1,mainr1,mainr2,statret;
  10.  
  11. procedure emailmenu;
  12.  
  13. implementation
  14.  
  15. procedure emailmenu;
  16. var lastread:integer;
  17.     m:mailrec;
  18.     incoming,outgoing:catalogrec;
  19.  
  20.   procedure addcatalog (var c:catalogrec; var m:mailrec; fpos:integer);
  21.   begin
  22.     m.fileindex:=fpos;
  23.     if c.nummail=maxcatalogsize
  24.       then c.additional:=c.additional+1
  25.       else begin
  26.         c.nummail:=c.nummail+1;
  27.         c.mail[c.nummail]:=m
  28.       end
  29.   end;
  30.  
  31.   procedure writenummail (var c:catalogrec; txt:mstr);
  32.   begin
  33.     writeln (^B^M'You have '^S,c.nummail+c.additional,^R' ',txt,
  34.              ' E-Mail',s(c.nummail),^R);
  35.     if c.additional>0
  36.       then writeln ('   Note: Of those, ',
  37.                      numthings (c.additional,'is','are'),' uncataloged.')
  38.   end;
  39.  
  40.   procedure readcatalogs;
  41.   var m:mailrec;
  42.       cnt:integer;
  43.   begin
  44.     seek (mfile,1);
  45.     incoming.nummail:=0;
  46.     incoming.additional:=0;
  47.     outgoing.nummail:=0;
  48.     outgoing.additional:=0;
  49.     for cnt:=1 to filesize(mfile)-1 do begin
  50.       read (mfile,m);
  51.       if m.sentto=unum
  52.         then addcatalog (incoming,m,cnt);
  53.       if match(m.sentby,unam)
  54.         then addcatalog (outgoing,m,cnt)
  55.     end
  56.   end;
  57.  
  58.   procedure readit (var m:mailrec);
  59.   begin
  60.     write (^B^M'Title:   '^S,m.title,^M'Sent by: '^S);
  61.     if m.anon
  62.       then
  63.         begin
  64.           write (anonymousstr);
  65.           if issysop then write (' (',m.sentby,')')
  66.         end
  67.       else write (m.sentby);
  68.     writeln (^M'Sent at: '^S,datestr(m.when),' at ',timestr(m.when));
  69.     writeln;
  70.     if not break then printtext (m.line)
  71.   end;
  72.  
  73.   procedure readincoming (n:integer);
  74.   var m:^mailrec;
  75.       cnt:integer;
  76.   begin
  77.     m:=addr(incoming.mail[n]);
  78.     readit (m^);
  79.     if not (m^.read) then begin
  80.       m^.read:=true;
  81.       seek (mfile,m^.fileindex);
  82.       write (mfile,m^)
  83.     end;
  84.     for cnt:=n+1 to incoming.nummail do
  85.       if match(incoming.mail[cnt].sentby,m^.sentby) then begin
  86.         writeln (^B^M'There''s more mail from ',m^.sentby,'!');
  87.         exit
  88.       end
  89.   end;
  90.  
  91.   procedure listmail (var c:catalogrec);
  92.   var n:integer;
  93.       u:userrec;
  94.       cnt:integer;
  95.       m:mailrec;
  96.   begin
  97.     write ('Num  ');
  98.     tab ('Title',30);
  99.     write ('New  Sent ');
  100.     if ofs(c)=ofs(incoming) then writeln ('by'^M) else writeln ('to'^M);
  101.     if break then exit;
  102.     for cnt:=1 to c.nummail do if not break then begin
  103.       m:=c.mail[cnt];
  104.       write (cnt:2,'.  ');
  105.       if not break then tab (m.title,30);
  106.       if not break then if m.read then write ('     ') else write ('New  ');
  107.       if match(m.sentby,unam)
  108.         then writeln (lookupuname (m.sentto))
  109.         else writeln (m.sentby)
  110.     end
  111.   end;
  112.  
  113.   procedure writemail (var c:catalogrec; num:integer);
  114.   begin
  115.     seek (mfile,c.mail[num].fileindex);
  116.     write (mfile,c.mail[num])
  117.   end;
  118.  
  119.   function checklastread:boolean;
  120.   begin
  121.     if (lastread<0) or (lastread>incoming.nummail) then lastread:=0;
  122.     checklastread:=lastread=0
  123.   end;
  124.  
  125.   function getmsgnumber (var c:catalogrec; txt:sstr):integer;
  126.   var n:integer;
  127.       inc:boolean;
  128.   begin
  129.     inc:=ofs(c)=ofs(incoming);
  130.     getmsgnumber:=0;
  131.     if c.nummail=0 then begin
  132.       if c.additional>0 then readcatalogs;
  133.       if c.nummail=0 then writestr (^M'Sorry, no mail!');
  134.       if inc then lastread:=0;
  135.       exit
  136.     end;
  137.     input:=copy(input,2,255);
  138.     if length(input)=0
  139.       then if inc
  140.         then n:=lastread
  141.         else n:=0
  142.       else n:=valu(input);
  143.     if (n<1) or (n>c.nummail) then begin
  144.       repeat
  145.         writestr (^M'E-Mail Number to '+txt+' [?/List]:');
  146.         if length(input)=0 then exit;
  147.         if input='?' then listmail (c)
  148.       until input<>'?';
  149.       n:=valu(input);
  150.       if (n<1) or (n>c.nummail) then n:=0
  151.     end;
  152.     getmsgnumber:=n
  153.   end;
  154.  
  155.   procedure deletemail (var c:catalogrec; n:integer);
  156.   begin
  157.     delmail (c.mail[n].fileindex);
  158.     writeln (c.mail[n].title,' by ',c.mail[n].sentby,' deleted.');
  159.     readcatalogs
  160.   end;
  161.  
  162.   procedure nextmail;
  163.   begin
  164.     lastread:=lastread+1;
  165.     if lastread>incoming.nummail
  166.       then
  167.         begin
  168.           lastread:=0;
  169.           if incoming.additional>0
  170.             then writeln ('You must delete some old mail first!')
  171.             else writeln ('Sorry, no more mail!')
  172.         end
  173.       else readincoming (lastread)
  174.   end;
  175.  
  176.   procedure readnum (n:integer);
  177.   begin
  178.     if (n<1) or (n>incoming.nummail) then begin
  179.       lastread:=0;
  180.       exit
  181.     end;
  182.     lastread:=n;
  183.     readincoming (n)
  184.   end;
  185.  
  186.   procedure readmail;
  187.   begin
  188.     readnum (getmsgnumber (incoming,'read'))
  189.   end;
  190.  
  191.   procedure listallmail;
  192.   begin
  193.     if incoming.nummail>0 then begin
  194.       writehdr ('incoming E-Mail');
  195.       listmail (incoming)
  196.     end;
  197.     if outgoing.nummail>0 then begin
  198.       writehdr ('outgoing E-Mail');
  199.       listmail (outgoing)
  200.     end
  201.   end;
  202.  
  203.   procedure newmail;
  204.   begin
  205.     lastread:=0;
  206.     repeat
  207.       lastread:=lastread+1;
  208.       if lastread>incoming.nummail then begin
  209.         writeln ('No (more) new mail.');
  210.         lastread:=0;
  211.         exit
  212.       end;
  213.       if not incoming.mail[lastread].read then begin
  214.         readincoming (lastread);
  215.         exit
  216.       end
  217.     until hungupon
  218.   end;
  219.  
  220.   procedure deleteincoming;
  221.   var n:integer;
  222.   begin
  223.     if checklastread then begin
  224.       n:=getmsgnumber (incoming,'delete');
  225.       if n=0 then exit;
  226.       lastread:=n
  227.     end;
  228.     deletemail (incoming,lastread);
  229.     lastread:=lastread-1
  230.   end;
  231.  
  232.   procedure killoutgoing;
  233.   var n:integer;
  234.   begin
  235.     n:=getmsgnumber (outgoing,'Kill');
  236.     if n<>0 then deletemail (outgoing,n)
  237.   end;
  238.  
  239.   procedure autoreply;
  240.   var n,un,line:integer;
  241.       me:message;
  242.       u:userrec;
  243.       uname:mstr;
  244.   begin
  245.     if checklastread then begin
  246.       n:=getmsgnumber (incoming,'Reply to');
  247.       if n=0 then exit;
  248.       lastread:=n
  249.     end;
  250.     with incoming.mail[lastread] do
  251.     begin
  252.      uname:=sentby;
  253.      if length(uname)=0 then exit;
  254.      un:=lookupuser (uname);
  255.      if un=0 then writeln ('User not found.') else begin
  256.        if anon and (ulvl<sysoplevel) then uname:=anonymousstr;
  257.        seek (ufile,un);
  258.        system.read (ufile,u);
  259.        if u.emailannounce>-1 then begin
  260.          writehdr (u.handle+'''s Announcement');
  261.          printtext (u.emailannounce)
  262.        end;
  263.        writehdr ('Sending E-Mail to '+uname);
  264.        emailing:=true;  {true}
  265.        line:=editor (me,false,'Re: '+title);
  266.        emailing:=false;
  267.        if line>=0 then addmail (un,line,me)
  268.      end
  269.     end;
  270.     readcatalogs
  271.   end;
  272.  
  273.   procedure viewoutgoing;
  274.   var n:integer;
  275.   begin
  276.     n:=getmsgnumber (outgoing,'view');
  277.     if n=0 then exit;
  278.     readit (outgoing.mail[n])
  279.   end;
  280.  
  281.   procedure showinfos;
  282.   var n:integer;
  283.   begin
  284.     if checklastread then begin
  285.       n:=getmsgnumber (incoming,'delete');
  286.       if n=0 then exit;
  287.       lastread:=n
  288.     end;
  289.     showinfoforms (incoming.mail[lastread].sentby)
  290.   end;
  291.  
  292.   procedure editmailuser;
  293.   var n:integer;
  294.       m:mstr;
  295.   begin
  296.     if checklastread then begin
  297.       n:=getmsgnumber (incoming,'edit the sender');
  298.       if n=0 then exit;
  299.       lastread:=n
  300.     end;
  301.     m:=incoming.mail[lastread].sentby;
  302.     n:=lookupuser (m);
  303.     if n=0 then begin
  304.       writeln (^B^R'User ',m,' not found!');
  305.       exit
  306.     end;
  307.     edituser (n)
  308.   end;
  309.  
  310.   procedure writecurmsg;
  311.   var b:boolean;
  312.   begin
  313.     b:=checklastread;
  314.     write (^B^M^R'Current Message: '^S);
  315.     if lastread=0
  316.       then writeln ('None'^R)
  317.       else with incoming.mail[lastread] do
  318.         writeln (^R'#'^S,lastread,^R': '^S,title,^R' sent by '^S,sentby,^R)
  319.   end;
  320.  
  321.   procedure showannouncement (un:integer);
  322.   var u:userrec;
  323.   begin
  324.     seek (ufile,un);
  325.     read (ufile,u);
  326.     if u.emailannounce>-1 then begin
  327.       writehdr (u.handle+'''s Announcement');
  328.       printtext (u.emailannounce)
  329.     end
  330.   end;
  331.  
  332.   procedure copymsg (var m:mailrec; un:integer);
  333.   var me:message;
  334.       line:integer;
  335.       b:boolean;
  336.   begin
  337.     me.anon:=m.anon;
  338.     me.title:='Was from '+m.sentby;
  339.     reloadtext (m.line,me);
  340.     showannouncement (un);
  341.     writestr ('Add a prologue (A to abort)? *');
  342.     if match(input,'a') then exit;
  343.     if yes then b:=reedit (me,true);
  344.     line:=maketext (me);
  345.     addmail (un,line,me);
  346.     readcatalogs
  347.   end;
  348.  
  349.   procedure copymail;
  350.   var n,un,line:integer;
  351.   begin
  352.     if checklastread then begin
  353.       n:=getmsgnumber (incoming,'copy');
  354.       if n=0 then exit;
  355.       lastread:=n
  356.     end;
  357.     n:=lastread;
  358.     writestr ('User to copy it to:');
  359.     if length(input)=0 then exit;
  360.     un:=lookupuser (input);
  361.     if un=0 then exit;
  362.     copymsg (incoming.mail[n],un)
  363.   end;
  364.  
  365.   procedure forwardmail;
  366.   var n,un:integer;
  367.   begin
  368.     if checklastread then begin
  369.       n:=getmsgnumber (incoming,'forward');
  370.       if n=0 then exit;
  371.       lastread:=n
  372.     end;
  373.     n:=lastread;
  374.     writestr ('User to forward it to:');
  375.     if length(input)=0 then exit;
  376.     un:=lookupuser (input);
  377.     if un=0 then exit;
  378.     copymsg (incoming.mail[n],un);
  379.     deletemail (incoming,n)
  380.   end;
  381.  
  382.   const groupclassstr:array [groupclass] of string[8]=
  383.           ('Public','Private','Personal');
  384.  
  385.   procedure opengfile;
  386.   begin
  387.     assign (gfile,'groups');
  388.     reset (gfile);
  389.     if ioresult<>0 then begin
  390.       close (gfile);
  391.       rewrite (gfile)
  392.     end
  393.   end;
  394.  
  395.   procedure seekgfile (n:integer);
  396.   begin
  397.     seek (gfile,n-1)
  398.   end;
  399.  
  400.   function ismember (var g:grouprec; n:integer):boolean;
  401.   var cnt:integer;
  402.   begin
  403.     ismember:=true;
  404.     for cnt:=1 to g.nummembers do
  405.       if g.members[cnt]=n then exit;
  406.     ismember:=false
  407.   end;
  408.  
  409.   function groupaccess (var g:grouprec):boolean;
  410.   begin
  411.     if issysop then begin
  412.       groupaccess:=true;
  413.       exit
  414.     end;
  415.     groupaccess:=false;
  416.     case g.class of
  417.       publicgroup:groupaccess:=true;
  418.       personalgroup:groupaccess:=g.creator=unum;
  419.       privategroup:groupaccess:=ismember (g,unum)
  420.     end
  421.   end;
  422.  
  423.   function lookupgroup (nm:mstr):integer;
  424.   var cnt:integer;
  425.       g:grouprec;
  426.   begin
  427.     lookupgroup:=0;
  428.     seekgfile (1);
  429.     for cnt:=1 to filesize(gfile) do begin
  430.       read (gfile,g);
  431.       if groupaccess(g)
  432.         then if match(g.name,nm)
  433.           then begin
  434.             lookupgroup:=cnt;
  435.             exit
  436.           end
  437.     end
  438.   end;
  439.  
  440.   procedure listgroups;
  441.   var g:grouprec;
  442.       cnt:integer;
  443.   begin
  444.     writestr (^M'Name                          Class'^M);
  445.     if break then exit;
  446.     seekgfile (1);
  447.     for cnt:=1 to filesize(gfile) do begin
  448.       read (gfile,g);
  449.       if groupaccess(g) then begin
  450.         tab (g.name,30);
  451.         writeln (groupclassstr[g.class]);
  452.         if break then exit
  453.       end
  454.     end
  455.   end;
  456.  
  457.   function getgroupclass:groupclass;
  458.   var k:char;
  459.   begin
  460.     repeat
  461.       input[1]:=#0;
  462.       writestr ('Group class p(U)blic, p(R)ivate, p(E)rsonal:');
  463.       k:=upcase(input[1]);
  464.       if k in ['U','R','E'] then begin
  465.         case k of
  466.           'U':getgroupclass:=publicgroup;
  467.           'R':getgroupclass:=privategroup;
  468.           'E':getgroupclass:=personalgroup
  469.         end;
  470.         exit
  471.       end
  472.     until hungupon;
  473.     getgroupclass:=publicgroup
  474.   end;
  475.  
  476.   procedure addmember (var g:grouprec; n:integer);
  477.   begin
  478.     if ismember (g,n) then begin
  479.       writestr ('That person is already a member!');
  480.       exit
  481.     end;
  482.     if g.nummembers=maxgroupsize then begin
  483.       writestr ('Sorry, group is full!');
  484.       exit
  485.     end;
  486.     g.nummembers:=g.nummembers+1;
  487.     g.members[g.nummembers]:=n
  488.   end;
  489.  
  490.   procedure addgroup;
  491.   var g:grouprec;
  492.       un:integer;
  493.   begin
  494.     writestr ('Group name:');
  495.     if (length(input)=0) or (input='?') then exit;
  496.     g.name:=input;
  497.     if lookupgroup (g.name)<>0 then begin
  498.       writestr (^M'Group already exists!');
  499.       exit
  500.     end;
  501.     g.class:=getgroupclass;
  502.     g.creator:=unum;
  503.     g.nummembers:=0;
  504.     writestr ('Include yourself in the group? *');
  505.     if yes then addmember (g,unum);
  506.     writestr (^M'Enter names of members, CR when done'^M);
  507.     repeat
  508.       writestr ('Member:');
  509.       if length(input)>0 then begin
  510.         un:=lookupuser (input);
  511.         if un=0
  512.           then writestr ('User not found!')
  513.           else addmember (g,un)
  514.       end
  515.     until hungupon or (length(input)=0) or (g.nummembers=maxgroupsize);
  516.     seek (gfile,filesize (gfile));
  517.     write (gfile,g);
  518.     writestr (^M'Group created!');
  519.     writelog (13,1,g.name)
  520.   end;
  521.  
  522.   function maybecreategroup (nm:mstr):integer;
  523.   begin
  524.     writestr ('Create group '+nm+'? *');
  525.     if yes then begin
  526.       addtochain (nm);
  527.       addgroup;
  528.       maybecreategroup:=lookupgroup (nm)
  529.     end else maybecreategroup:=0
  530.   end;
  531.  
  532.   function getgroupnum:integer;
  533.   var groupname:mstr;
  534.       gn:integer;
  535.       g:grouprec;
  536.   begin
  537.     getgroupnum:=0;
  538.     groupname:=copy(input,2,255);
  539.     repeat
  540.       if length(groupname)=0 then begin
  541.         writestr (^M'  Group name [?/List]:');
  542.         if length(input)=0 then exit;
  543.         if input[1]='/' then delete (input,1,1);
  544.         if length(input)=0 then exit;
  545.         groupname:=input
  546.       end;
  547.       if groupname='?' then begin
  548.         listgroups;
  549.         groupname:=''
  550.       end
  551.     until length(groupname)>0;
  552.     gn:=lookupgroup (groupname);
  553.     if gn=0 then begin
  554.       writestr ('Group not found!');
  555.       gn:=maybecreategroup (groupname);
  556.       if gn=0 then exit
  557.     end;
  558.     seekgfile (gn);
  559.     read (gfile,g);
  560.     if not groupaccess(g)
  561.       then writestr ('Sorry, you may not access that group!')
  562.       else getgroupnum:=gn
  563.   end;
  564.  
  565.   procedure sendmail;
  566.   var g:grouprec;
  567.  
  568.     procedure sendit (showeach:boolean);
  569.     var un,line,cnt:integer;
  570.         me:message;
  571.  
  572.       procedure addit (n:integer);
  573.       begin
  574.         if n<>unum then begin
  575.           if showeach then writeln (lookupuname(n));
  576.           addmail (n,line,me)
  577.         end else deletetext (line)
  578.       end;
  579.  
  580.     begin
  581.       if g.nummembers<1 then exit;
  582.       writehdr ('Sending E-Mail to '+g.name);
  583.       sendstr:=g.name;
  584.       nosendprompt:=true;
  585.       line:=editor (me,true,'Sending E-Mail to '+g.name);
  586.       nosendprompt:=false;
  587.       sendstr:='';
  588.       if line<0 then exit;
  589.       addit (g.members[1]);
  590.       if g.nummembers=1 then exit;
  591.       writeln (^B^M);
  592.       for cnt:=2 to g.nummembers do begin
  593.         un:=g.members[cnt];
  594.         if un<>unum then begin
  595.           line:=maketext (me);
  596.           if line<0 then begin
  597.             writeln (cnt,' of ',g.nummembers,' completed.');
  598.             exit
  599.           end;
  600.           addit (un);
  601.           if emails>32760 then emails:=0;
  602.           emails:=emails+1;
  603.         end
  604.       end;
  605.       readcatalogs
  606.     end;
  607.  
  608.     procedure sendtogroup;
  609.     var gn:integer;
  610.     begin
  611.       gn:=getgroupnum;
  612.       if gn=0 then exit;
  613.       seekgfile (gn);
  614.       read (gfile,g);
  615.       sendit (true)
  616.     end;
  617.  
  618.     procedure sendtousers;
  619.     var cnt,un:integer;
  620.     begin
  621.       g.name:=input;
  622.       un:=lookupuser (g.name);
  623.       if un=0 then begin
  624.         writestr (^M'User not found.');
  625.         exit
  626.       end;
  627.       g.nummembers:=1;
  628.       g.members[1]:=un;
  629.       cnt:=1;
  630.       showannouncement (un);
  631.       repeat
  632.         writestr ('Carbon copy #'+strr(cnt)+' to:');
  633.         if length(input)>0 then begin
  634.           un:=lookupuser (input);
  635.           if un=0
  636.             then writestr (^M'User not found!'^M)
  637.             else if ismember (g,un)
  638.               then writestr (^M'User is already receiving a copy!')
  639.               else begin
  640.                 cnt:=cnt+1;
  641.                 g.nummembers:=cnt;
  642.                 g.members[cnt]:=un;
  643.                 showannouncement (un)
  644.               end
  645.         end
  646.       until (length(input)=0) or (cnt=maxgroupsize);
  647.       sendit (g.nummembers>1)
  648.     end;
  649.  
  650.   begin
  651.     writestr ('User to send E-Mail to [''/'' for Group]:');
  652.     if length(input)<>0
  653.       then if input[1]='/'
  654.         then sendtogroup
  655.         else sendtousers
  656.   end;
  657.  
  658.   procedure zippymail;
  659.   var un:integer;
  660.       me:message;
  661.       l:integer;
  662.   begin
  663.     writestr ('Send mail to:');
  664.     if length(input)=0 then exit;
  665.     un:=lookupuser (input);
  666.     if un=0 then begin
  667.       writestr ('No such user!');
  668.       exit
  669.     end;
  670.     titlestr:='Zippy Mail';
  671.     l:=editor (me,false,'Zippy Mail');
  672.     if l<0 then exit;
  673.     me.title:='-----';
  674.     me.anon:=false;
  675.     addmail (un,l,me);
  676.     readcatalogs
  677.   end;
  678.  
  679.   {overlay} procedure sysopmail;
  680.  
  681.     function sysopreadnum (var n:integer):boolean;
  682.     var m:mailrec;
  683.         k:char;
  684.         done:boolean;
  685.  
  686.       procedure showit;
  687.       begin
  688.         writeln (^B^N^M'Number  '^S,n,
  689.                      ^M'Sent by '^S,m.sentby,
  690.                      ^M'Sent to '^S,lookupuname (m.sentto),
  691.                      ^M'Sent on '^S,datestr(m.when),' at ',timestr(m.when),
  692.                      ^M'Title:  '^S,m.title,^M);
  693.         printtext (m.line);
  694.       end;
  695.  
  696.       procedure changen (m:integer);
  697.       var r2:integer;
  698.       begin
  699.         r2:=filesize(mfile)-1;
  700.         if (m<1) or (m>r2) then begin
  701.           writestr ('Continue scan at [1-'+strr(r2)+']:');
  702.           m:=valu(input)
  703.         end;
  704.         if (m>=1) and (m<=r2) then begin
  705.           n:=m-1;
  706.           done:=true
  707.         end
  708.       end;
  709.  
  710.     var q:integer;
  711.     begin
  712.       sysopreadnum:=false;
  713.       seek (mfile,n);
  714.       read (mfile,m);
  715.       showit;
  716.       repeat
  717.         done:=false;
  718.         q:=menu ('E-Mail Scan','ESCAN','QSERDNAC_#');
  719.         if q<0
  720.           then changen (-q)
  721.           else case q of
  722.             1:sysopreadnum:=true;
  723.             2:sendmail;
  724.             3:edituser(lookupuser(m.sentby));
  725.             4:edituser(m.sentto);
  726.             5:delmail(n);
  727.             6,9:done:=true;
  728.             7:showit;
  729.             8:changen (0);
  730.           end
  731.       until (q=1) or done or hungupon
  732.     end;
  733.  
  734.     procedure someoneelse;
  735.     var t,last:integer;
  736.     begin
  737.       writestr (^M'User name to look at:');
  738.       if (length(input)=0) or hungupon then exit;
  739.       writeln;
  740.       t:=lookupuser (input);
  741.       if t=0 then begin
  742.         writestr ('No such user!');
  743.         exit
  744.       end;
  745.       writelog (14,1,input);
  746.       writestr ('Looking in mailbox...');
  747.       last:=searchmail(0,t);
  748.       if last=0 then writestr ('No mail.');
  749.       while last<>0 do begin
  750.         seek (mfile,last);
  751.         read (mfile,m);
  752.         if sysopreadnum (last) or hungupon then exit;
  753.         last:=searchmail(last,t)
  754.       end;
  755.       writeln (^B^M'No more mail!')
  756.     end;
  757.  
  758.     procedure scanall;
  759.     var r1,r2:integer;
  760.         u:userrec;
  761.         n:mstr;
  762.     begin
  763.       r2:=filesize(mfile)-1;
  764.       writestr ('Start scanning at [1-'+strr(r2)+']:');
  765.       if length(input)=0 then r1:=1 else r1:=valu(input);
  766.       if (r1<1) or (r1>r2) then exit;
  767.       writelog (14,2,'');
  768.       while r1<filesize(mfile) do begin
  769.         seek (mfile,r1);
  770.         read (mfile,m);
  771.         if m.sentto<>0 then
  772.           if sysopreadnum (r1) then exit;
  773.         r1:=r1+1
  774.       end;
  775.       writeln (^B^M'No more mail!')
  776.     end;
  777.  
  778.     procedure groupflags;
  779.     var gn,bn,un,cnt:integer;
  780.         bname:sstr;
  781.         ac:accesstype;
  782.         g:grouprec;
  783.         u:userrec;
  784.     begin
  785.       writestr ('Grant all group members access to a sub-board'^M);
  786.       gn:=getgroupnum;
  787.       if gn=0 then exit;
  788.       writestr ('  Sub-board access name/number:');
  789.       writeln;
  790.       bname:=input;
  791.       opentempbdfile;
  792.       bn:=searchboard(bname);
  793.       closetempbdfile;
  794.       if bn=-1 then begin
  795.         writeln ('No such board!');
  796.         exit
  797.       end;
  798.       writelog (14,3,bname);
  799.       for cnt:=1 to g.nummembers do begin
  800.         un:=g.members[cnt];
  801.         writeln (lookupuname(un));
  802.         seek (ufile,un);
  803.         read (ufile,u);
  804.         setuseraccflag (u,bn,letin);
  805.         seek (ufile,un);
  806.         write (ufile,u)
  807.       end
  808.     end;
  809.  
  810.     procedure deleterange;
  811.     var first,last,num,cnt:integer;
  812.     begin
  813.       writehdr ('Mass Mail Delete');
  814.       parserange (filesize(mfile)-1,first,last);
  815.       if first=0 then exit;
  816.       num:=last-first;
  817.       if num<>1 then begin
  818.         writeln ('Warning! ',num,' pieces of mail will be deleted!');
  819.         writestr ('Are you sure? *');
  820.         if not yes then exit
  821.       end;
  822.       for cnt:=last downto first do begin
  823.         delmail (cnt);
  824.         write (cnt,' ');
  825.         if break then begin
  826.           writestr (^B^M'Aborted!');
  827.           exit
  828.         end
  829.       end;
  830.       writeln
  831.     end;
  832.  
  833.   var q:integer;
  834.   begin
  835.     repeat
  836.       q:=menu ('E-Mail Sysop','ESYSOP','QLSGD');
  837.       case q of
  838.         2:someoneelse;
  839.         3:scanall;
  840.         4:groupflags;
  841.         5:deleterange;
  842.       end
  843.     until (q=1) or hungupon;
  844.     readcatalogs
  845.   end;
  846.  
  847.   {overlay} procedure announcement;
  848.  
  849.     procedure delannouncement;
  850.     begin
  851.       if urec.emailannounce=-1 then begin
  852.         writestr (^M'You don''t HAVE an announcement.');
  853.         exit
  854.       end;
  855.       deletetext (urec.emailannounce);
  856.       urec.emailannounce:=-1;
  857.       writeurec;
  858.       writestr (^M'Deleted.')
  859.     end;
  860.  
  861.     procedure createannouncement;
  862.     var me:message;
  863.     begin
  864.       if urec.emailannounce>=0 then deletetext (urec.emailannounce);
  865.       titlestr:='User Announcement';
  866.       urec.emailannounce:=editor (me,false,'User Announcement');
  867.       writeurec
  868.     end;
  869.  
  870.   var k:char;
  871.   begin
  872.     if urec.emailannounce>=0
  873.       then showannouncement (unum)
  874.       else writestr ('You don''t have an announcement right now.');
  875.     writestr (^M'[C]reate/replace, [D]elete, or [Q]uit:');
  876.     if length(input)=0 then exit;
  877.     k:=upcase(input[1]);
  878.     case k of
  879.       'D':delannouncement;
  880.       'C':createannouncement
  881.     end
  882.   end;
  883.  
  884.   {overlay} procedure groupediting;
  885.   var curgroup:integer;
  886.       cg:grouprec;
  887.  
  888.     procedure selectgroup;
  889.     var n:integer;
  890.         g:grouprec;
  891.     begin
  892.       delete (input,1,1);
  893.       repeat
  894.         if length(input)=0 then writestr ('Select group [?/List]:');
  895.         if length(input)=0 then exit;
  896.         if input='?' then begin
  897.           listgroups;
  898.           n:=0;
  899.           input[0]:=#0
  900.         end else begin
  901.           n:=lookupgroup (input);
  902.           if n=0 then begin
  903.             writestr ('Group not found!');
  904.             exit
  905.           end
  906.         end
  907.       until n>0;
  908.       seekgfile (n);
  909.       read (gfile,g);
  910.       if groupaccess(g) then begin
  911.         curgroup:=n;
  912.         cg:=g
  913.       end else writestr ('You can''t access that group.')
  914.     end;
  915.  
  916.     function nocurgroup:boolean;
  917.     begin
  918.       nocurgroup:=curgroup=0;
  919.       if curgroup=0 then writestr ('No group as been S)elected!')
  920.     end;
  921.  
  922.     function notcreator:boolean;
  923.     var b:boolean;
  924.     begin
  925.       if nocurgroup then b:=true else begin
  926.         b:=(unum<>cg.creator) and (not issysop);
  927.         if b then writestr ('You aren''t the creator of this group!')
  928.       end;
  929.       notcreator:=b;
  930.     end;
  931.  
  932.     procedure writecurgroup;
  933.     begin
  934.       seekgfile (curgroup);
  935.       write (gfile,cg)
  936.     end;
  937.  
  938.     procedure deletegroup;
  939.     var cnt:integer;
  940.         g:grouprec;
  941.     begin
  942.       if notcreator then exit;
  943.       writestr ('Delete group '+cg.name+': Are you sure? *');
  944.       if not yes then exit;
  945.       writelog (13,2,cg.name);
  946.       for cnt:=curgroup to filesize(gfile)-1 do begin
  947.         seekgfile (cnt+1);
  948.         read (gfile,g);
  949.         seekgfile (cnt);
  950.         write (gfile,g)
  951.       end;
  952.       seek (gfile,filesize(gfile)-1);
  953.       truncate (gfile);
  954.       curgroup:=0
  955.     end;
  956.  
  957.     procedure listmembers;
  958.     var cnt:integer;
  959.     begin
  960.       if nocurgroup then exit;
  961.       writeln ('Creator:           '^S,lookupuname (cg.creator));
  962.       writeln ('Number of members: '^S,cg.nummembers,^M);
  963.       for cnt:=1 to cg.nummembers do begin
  964.         if break then exit;
  965.         writeln (cnt:2,'. ',lookupuname (cg.members[cnt]))
  966.       end
  967.     end;
  968.  
  969.     procedure readdmember;
  970.     var n:integer;
  971.     begin
  972.       if notcreator then exit;
  973.       writestr ('User to add:');
  974.       if length(input)=0 then exit;
  975.       n:=lookupuser (input);
  976.       if n=0
  977.         then writestr ('User not found!')
  978.         else begin
  979.           addmember (cg,n);
  980.           writecurgroup
  981.         end
  982.     end;
  983.  
  984.     procedure removemember;
  985.  
  986.       procedure removemembernum (n:integer);
  987.       var cnt:integer;
  988.       begin
  989.         cg.nummembers:=cg.nummembers-1;
  990.         for cnt:=n to cg.nummembers do cg.members[cnt]:=cg.members[cnt+1];
  991.         writecurgroup;
  992.         writestr ('Member removed.')
  993.       end;
  994.  
  995.     var cnt,n:integer;
  996.     begin
  997.       if notcreator then exit;
  998.       repeat
  999.         writestr ('User to remove [?/List]:');
  1000.         if length(input)=0 then exit;
  1001.         if input='?' then begin
  1002.           input[0]:=#0;
  1003.           listmembers
  1004.         end
  1005.       until length(input)>0;
  1006.       n:=lookupuser (input);
  1007.       if n=0 then begin
  1008.         writestr ('User not found!');
  1009.         exit
  1010.       end;
  1011.       for cnt:=1 to cg.nummembers do if cg.members[cnt]=n then begin
  1012.         removemembernum (cnt);
  1013.         exit
  1014.       end;
  1015.       writestr ('User isn''t in the group!')
  1016.     end;
  1017.  
  1018.     procedure setclass;
  1019.     begin
  1020.       if notcreator then exit;
  1021.       writeln ('Current class: '^S,groupclassstr [cg.class],^M);
  1022.       cg.class:=getgroupclass;
  1023.       writecurgroup
  1024.     end;
  1025.  
  1026.     procedure setcreator;
  1027.     var m:mstr;
  1028.         n:integer;
  1029.     begin
  1030.       if notcreator then exit;
  1031.       writeln ('Current creator: '^S,lookupuname(cg.creator),^M);
  1032.       writestr ('Enter new creator:');
  1033.       if length(input)=0 then exit;
  1034.       n:=lookupuser(input);
  1035.       if n=0 then begin
  1036.         writestr ('User not found!');
  1037.         exit
  1038.       end;
  1039.       cg.creator:=n;
  1040.       writecurgroup;
  1041.       if (n<>unum) and (not issysop) then curgroup:=0
  1042.     end;
  1043.  
  1044.     procedure addbylevel;
  1045.     var n,cnt:integer;
  1046.         u:userrec;
  1047.     begin
  1048.       if notcreator then exit;
  1049.       writestr ('Let in all people over level:');
  1050.       n:=valu(input);
  1051.       if n=0 then exit;
  1052.       seek (ufile,1);
  1053.       for cnt:=1 to numusers do begin
  1054.         read (ufile,u);
  1055.         if (length(u.handle)>0) and (u.level>=n) then begin
  1056.           if cg.nummembers=maxgroupsize then begin
  1057.             writestr ('Sorry, group is full!');
  1058.             exit
  1059.           end;
  1060.           addmember (cg,cnt)
  1061.         end
  1062.       end
  1063.     end;
  1064.  
  1065.   var q:integer;
  1066.   begin
  1067.     curgroup:=0;
  1068.     repeat
  1069.       write (^B^M^M^R'Group selected: '^S);
  1070.       if curgroup=0
  1071.         then writeln ('None')
  1072.         else writeln (cg.name);
  1073.       q:=menu ('Group Editing','GROUP','QS*LGDVMRCAE');
  1074.       case q of
  1075.         2,3:selectgroup;
  1076.         4:listgroups;
  1077.         5:addgroup;
  1078.         6:deletegroup;
  1079.         7:listmembers;
  1080.         8:readdmember;
  1081.         9:removemember;
  1082.         10:setcreator;
  1083.         11:setclass;
  1084.         12:addbylevel
  1085.       end
  1086.     until hungupon or (q=1)
  1087.   end;
  1088.  
  1089. var q:integer;
  1090. begin
  1091.   cursection:=emailsysop;
  1092.   writehdr ('TCS Electronic Mail Service');
  1093.   opengfile;
  1094.   readcatalogs;
  1095.   writenummail (incoming,'incoming');
  1096.   writenummail (outgoing,'outgoing');
  1097.   lastread:=0;
  1098.   repeat
  1099.     writecurmsg;
  1100.     q:=menu ('E-Mail Command','EMAIL','QRSLN_%@DKAV#E@CFHGI@Z');
  1101.     if q<0
  1102.       then readnum (abs(q))
  1103.       else case q of
  1104.         2:autoreply;
  1105.         3:sendmail;
  1106.         4:listallmail;
  1107.         5:newmail;
  1108.         6:nextmail;
  1109.         7:sysopmail;
  1110.         8:deleteincoming;
  1111.         9:killoutgoing;
  1112.         10:announcement;
  1113.         11:viewoutgoing;
  1114.         13:editmailuser;
  1115.         14:copymail;
  1116.         15:forwardmail;
  1117.         16:help ('Email.HLP');
  1118.         17:groupediting;
  1119.         18:showinfos;
  1120.         19:zippymail
  1121.       end
  1122.   until hungupon or (q=1);
  1123.   close (gfile)
  1124. end;
  1125.  
  1126. begin
  1127. end.
  1128.