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

  1. {$R-,S-,I-,D-,T-,F-,V-,B-,N-,L+ }
  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;
  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 ',c.nummail+c.additional,' ',txt,
  34.              ' message',s(c.nummail));
  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'Message 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 mail');
  195.       listmail (incoming)
  196.     end;
  197.     if outgoing.nummail>0 then begin
  198.       writehdr ('Outgoing 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:integer;
  241.   begin
  242.     if checklastread then begin
  243.       n:=getmsgnumber (incoming,'reply to');
  244.       if n=0 then exit;
  245.       lastread:=n
  246.     end;
  247.     with incoming.mail[lastread] do
  248.       sendmailto (sentby,anon);
  249.     readcatalogs
  250.   end;
  251.  
  252.   procedure viewoutgoing;
  253.   var n:integer;
  254.   begin
  255.     n:=getmsgnumber (outgoing,'view');
  256.     if n=0 then exit;
  257.     readit (outgoing.mail[n])
  258.   end;
  259.  
  260.   procedure showinfos;
  261.   var n:integer;
  262.   begin
  263.     if checklastread then begin
  264.       n:=getmsgnumber (incoming,'delete');
  265.       if n=0 then exit;
  266.       lastread:=n
  267.     end;
  268.     showinfoforms (incoming.mail[lastread].sentby)
  269.   end;
  270.  
  271.   procedure editmailuser;
  272.   var n:integer;
  273.       m:mstr;
  274.   begin
  275.     if checklastread then begin
  276.       n:=getmsgnumber (incoming,'edit the sender');
  277.       if n=0 then exit;
  278.       lastread:=n
  279.     end;
  280.     m:=incoming.mail[lastread].sentby;
  281.     n:=lookupuser (m);
  282.     if n=0 then begin
  283.       writeln (^B^R'User ',m,' not found!');
  284.       exit
  285.     end;
  286.     edituser (n)
  287.   end;
  288.  
  289.   procedure writecurmsg;
  290.   var b:boolean;
  291.   begin
  292.     b:=checklastread;
  293.     write (^B^M'Current msg: ');
  294.     if lastread=0
  295.       then writeln ('None')
  296.       else with incoming.mail[lastread] do
  297.         writeln ('#',lastread,': ',title,' sent by ',sentby)
  298.   end;
  299.  
  300.   procedure showannouncement (un:integer);
  301.   var u:userrec;
  302.   begin
  303.     seek (ufile,un);
  304.     read (ufile,u);
  305.     if u.emailannounce>-1 then begin
  306.       writehdr (u.handle+'''s Announcement');
  307.       printtext (u.emailannounce)
  308.     end
  309.   end;
  310.  
  311.   procedure copymsg (var m:mailrec; un:integer);
  312.   var me:message;
  313.       line:integer;
  314.       b:boolean;
  315.   begin
  316.     me.anon:=m.anon;
  317.     me.title:='Was from '+m.sentby;
  318.     reloadtext (m.line,me);
  319.     showannouncement (un);
  320.     writestr ('Add a prologue (A to abort)? *');
  321.     if match(input,'a') then exit;
  322.     if yes then b:=reedit (me,true);
  323.     line:=maketext (me);
  324.     addmail (un,line,me);
  325.     readcatalogs
  326.   end;
  327.  
  328.   procedure copymail;
  329.   var n,un,line:integer;
  330.   begin
  331.     if checklastread then begin
  332.       n:=getmsgnumber (incoming,'copy');
  333.       if n=0 then exit;
  334.       lastread:=n
  335.     end;
  336.     n:=lastread;
  337.     writestr ('User to copy it to:');
  338.     if length(input)=0 then exit;
  339.     un:=lookupuser (input);
  340.     if un=0 then exit;
  341.     copymsg (incoming.mail[n],un)
  342.   end;
  343.  
  344.   procedure forwardmail;
  345.   var n,un:integer;
  346.   begin
  347.     if checklastread then begin
  348.       n:=getmsgnumber (incoming,'forward');
  349.       if n=0 then exit;
  350.       lastread:=n
  351.     end;
  352.     n:=lastread;
  353.     writestr ('User to forward it to:');
  354.     if length(input)=0 then exit;
  355.     un:=lookupuser (input);
  356.     if un=0 then exit;
  357.     copymsg (incoming.mail[n],un);
  358.     deletemail (incoming,n)
  359.   end;
  360.  
  361.   const groupclassstr:array [groupclass] of string[8]=
  362.           ('Public','Private','Personal');
  363.  
  364.   procedure opengfile;
  365.   begin
  366.     assign (gfile,'groups');
  367.     reset (gfile);
  368.     if ioresult<>0 then begin
  369.       close (gfile);
  370.       rewrite (gfile)
  371.     end
  372.   end;
  373.  
  374.   procedure seekgfile (n:integer);
  375.   begin
  376.     seek (gfile,n-1)
  377.   end;
  378.  
  379.   function ismember (var g:grouprec; n:integer):boolean;
  380.   var cnt:integer;
  381.   begin
  382.     ismember:=true;
  383.     for cnt:=1 to g.nummembers do
  384.       if g.members[cnt]=n then exit;
  385.     ismember:=false
  386.   end;
  387.  
  388.   function groupaccess (var g:grouprec):boolean;
  389.   begin
  390.     if issysop then begin
  391.       groupaccess:=true;
  392.       exit
  393.     end;
  394.     groupaccess:=false;
  395.     case g.class of
  396.       publicgroup:groupaccess:=true;
  397.       personalgroup:groupaccess:=g.creator=unum;
  398.       privategroup:groupaccess:=ismember (g,unum)
  399.     end
  400.   end;
  401.  
  402.   function lookupgroup (nm:mstr):integer;
  403.   var cnt:integer;
  404.       g:grouprec;
  405.   begin
  406.     lookupgroup:=0;
  407.     seekgfile (1);
  408.     for cnt:=1 to filesize(gfile) do begin
  409.       read (gfile,g);
  410.       if groupaccess(g)
  411.         then if match(g.name,nm)
  412.           then begin
  413.             lookupgroup:=cnt;
  414.             exit
  415.           end
  416.     end
  417.   end;
  418.  
  419.   procedure listgroups;
  420.   var g:grouprec;
  421.       cnt:integer;
  422.   begin
  423.     writestr (^M'Name                          Class'^M);
  424.     if break then exit;
  425.     seekgfile (1);
  426.     for cnt:=1 to filesize(gfile) do begin
  427.       read (gfile,g);
  428.       if groupaccess(g) then begin
  429.         tab (g.name,30);
  430.         writeln (groupclassstr[g.class]);
  431.         if break then exit
  432.       end
  433.     end
  434.   end;
  435.  
  436.   function getgroupclass:groupclass;
  437.   var k:char;
  438.   begin
  439.     repeat
  440.       input[1]:=#0;
  441.       writestr ('Group class p(U)blic, p(R)ivate, p(E)rsonal:');
  442.       k:=upcase(input[1]);
  443.       if k in ['U','R','E'] then begin
  444.         case k of
  445.           'U':getgroupclass:=publicgroup;
  446.           'R':getgroupclass:=privategroup;
  447.           'E':getgroupclass:=personalgroup
  448.         end;
  449.         exit
  450.       end
  451.     until hungupon;
  452.     getgroupclass:=publicgroup
  453.   end;
  454.  
  455.   procedure addmember (var g:grouprec; n:integer);
  456.   begin
  457.     if ismember (g,n) then begin
  458.       writestr ('That person is already a member!');
  459.       exit
  460.     end;
  461.     if g.nummembers=maxgroupsize then begin
  462.       writestr ('Sorry, group is full!');
  463.       exit
  464.     end;
  465.     g.nummembers:=g.nummembers+1;
  466.     g.members[g.nummembers]:=n
  467.   end;
  468.  
  469.   procedure addgroup;
  470.   var g:grouprec;
  471.       un:integer;
  472.   begin
  473.     writestr ('Group name:');
  474.     if (length(input)=0) or (input='?') then exit;
  475.     g.name:=input;
  476.     if lookupgroup (g.name)<>0 then begin
  477.       writestr (^M'Group already exists!');
  478.       exit
  479.     end;
  480.     g.class:=getgroupclass;
  481.     g.creator:=unum;
  482.     g.nummembers:=0;
  483.     writestr ('Include yourself in the group? *');
  484.     if yes then addmember (g,unum);
  485.     writestr (^M'Enter names of members, CR when done'^M);
  486.     repeat
  487.       writestr ('Member:');
  488.       if length(input)>0 then begin
  489.         un:=lookupuser (input);
  490.         if un=0
  491.           then writestr ('User not found!')
  492.           else addmember (g,un)
  493.       end
  494.     until hungupon or (length(input)=0) or (g.nummembers=maxgroupsize);
  495.     seek (gfile,filesize (gfile));
  496.     write (gfile,g);
  497.     writestr (^M'Group created!');
  498.     writelog (13,1,g.name)
  499.   end;
  500.  
  501.   function maybecreategroup (nm:mstr):integer;
  502.   begin
  503.     writestr ('Create group '+nm+'? *');
  504.     if yes then begin
  505.       addtochain (nm);
  506.       addgroup;
  507.       maybecreategroup:=lookupgroup (nm)
  508.     end else maybecreategroup:=0
  509.   end;
  510.  
  511.   function getgroupnum:integer;
  512.   var groupname:mstr;
  513.       gn:integer;
  514.       g:grouprec;
  515.   begin
  516.     getgroupnum:=0;
  517.     groupname:=copy(input,2,255);
  518.     repeat
  519.       if length(groupname)=0 then begin
  520.         writestr (^M'  Group name [?=list]:');
  521.         if length(input)=0 then exit;
  522.         if input[1]='/' then delete (input,1,1);
  523.         if length(input)=0 then exit;
  524.         groupname:=input
  525.       end;
  526.       if groupname='?' then begin
  527.         listgroups;
  528.         groupname:=''
  529.       end
  530.     until length(groupname)>0;
  531.     gn:=lookupgroup (groupname);
  532.     if gn=0 then begin
  533.       writestr ('Group not found!');
  534.       gn:=maybecreategroup (groupname);
  535.       if gn=0 then exit
  536.     end;
  537.     seekgfile (gn);
  538.     read (gfile,g);
  539.     if not groupaccess(g)
  540.       then writestr ('Sorry, you may not access that group!')
  541.       else getgroupnum:=gn
  542.   end;
  543.  
  544.   procedure sendmail;
  545.   var g:grouprec;
  546.  
  547.     procedure sendit (showeach:boolean);
  548.     var un,line,cnt:integer;
  549.         me:message;
  550.  
  551.       procedure addit (n:integer);
  552.       begin
  553.         if n<>unum then begin
  554.           if showeach then writeln (lookupuname(n));
  555.           addmail (n,line,me)
  556.         end else deletetext (line)
  557.       end;
  558.  
  559.     begin
  560.       if g.nummembers<1 then exit;
  561.       writehdr ('Sending mail to '+g.name);
  562.       line:=editor (me,true);
  563.       if line<0 then exit;
  564.       addit (g.members[1]);
  565.       if g.nummembers=1 then exit;
  566.       writeln (^B^M);
  567.       for cnt:=2 to g.nummembers do begin
  568.         un:=g.members[cnt];
  569.         if un<>unum then begin
  570.           line:=maketext (me);
  571.           if line<0 then begin
  572.             writeln (cnt,' of ',g.nummembers,' completed.');
  573.             exit
  574.           end;
  575.           addit (un)
  576.         end
  577.       end;
  578.       readcatalogs
  579.     end;
  580.  
  581.     procedure sendtogroup;
  582.     var gn:integer;
  583.     begin
  584.       gn:=getgroupnum;
  585.       if gn=0 then exit;
  586.       seekgfile (gn);
  587.       read (gfile,g);
  588.       sendit (true)
  589.     end;
  590.  
  591.     procedure sendtousers;
  592.     var cnt,un:integer;
  593.     begin
  594.       g.name:=input;
  595.       un:=lookupuser (g.name);
  596.       if un=0 then begin
  597.         writestr (^M'User not found.');
  598.         exit
  599.       end;
  600.       g.nummembers:=1;
  601.       g.members[1]:=un;
  602.       cnt:=1;
  603.       showannouncement (un);
  604.       repeat
  605.         writestr ('Carbon copy #'+strr(cnt)+' to:');
  606.         if length(input)>0 then begin
  607.           un:=lookupuser (input);
  608.           if un=0
  609.             then writestr (^M'User not found!'^M)
  610.             else if ismember (g,un)
  611.               then writestr (^M'User is already receiving a copy!')
  612.               else begin
  613.                 cnt:=cnt+1;
  614.                 g.nummembers:=cnt;
  615.                 g.members[cnt]:=un;
  616.                 showannouncement (un)
  617.               end
  618.         end
  619.       until (length(input)=0) or (cnt=maxgroupsize);
  620.       sendit (g.nummembers>1)
  621.     end;
  622.  
  623.   begin
  624.     writestr ('User to send mail to:');
  625.     if length(input)<>0
  626.       then if input[1]='/'
  627.         then sendtogroup
  628.         else sendtousers
  629.   end;
  630.  
  631.   procedure zippymail;
  632.   var un:integer;
  633.       me:message;
  634.       l:integer;
  635.   begin
  636.     writestr ('Send mail to:');
  637.     if length(input)=0 then exit;
  638.     un:=lookupuser (input);
  639.     if un=0 then begin
  640.       writestr ('No such user!');
  641.       exit
  642.     end;
  643.     l:=editor (me,false);
  644.     if l<0 then exit;
  645.     me.title:='-----';
  646.     me.anon:=false;
  647.     addmail (un,l,me);
  648.     readcatalogs
  649.   end;
  650.  
  651.   {overlay} procedure sysopmail;
  652.  
  653.     function sysopreadnum (var n:integer):boolean;
  654.     var m:mailrec;
  655.         k:char;
  656.         done:boolean;
  657.  
  658.       procedure showit;
  659.       begin
  660.         writeln (^B^N^M'Number  '^S,n,
  661.                      ^M'Sent by '^S,m.sentby,
  662.                      ^M'Sent to '^S,lookupuname (m.sentto),
  663.                      ^M'Sent on '^S,datestr(m.when),' at ',timestr(m.when),
  664.                      ^M'Title:  '^S,m.title,^M);
  665.         printtext (m.line);
  666.       end;
  667.  
  668.       procedure changen (m:integer);
  669.       var r2:integer;
  670.       begin
  671.         r2:=filesize(mfile)-1;
  672.         if (m<1) or (m>r2) then begin
  673.           writestr ('Continue scan at [1-'+strr(r2)+']:');
  674.           m:=valu(input)
  675.         end;
  676.         if (m>=1) and (m<=r2) then begin
  677.           n:=m-1;
  678.           done:=true
  679.         end
  680.       end;
  681.  
  682.     var q:integer;
  683.     begin
  684.       sysopreadnum:=false;
  685.       seek (mfile,n);
  686.       read (mfile,m);
  687.       showit;
  688.       repeat
  689.         done:=false;
  690.         q:=menu ('E-Mail Scan','ESCAN','QSERDNAC_#');
  691.         if q<0
  692.           then changen (-q)
  693.           else case q of
  694.             1:sysopreadnum:=true;
  695.             2:sendmail;
  696.             3:edituser(lookupuser(m.sentby));
  697.             4:edituser(m.sentto);
  698.             5:delmail(n);
  699.             6,9:done:=true;
  700.             7:showit;
  701.             8:changen (0);
  702.           end
  703.       until (q=1) or done or hungupon
  704.     end;
  705.  
  706.     procedure someoneelse;
  707.     var t,last:integer;
  708.     begin
  709.       writestr (^M'User name to look at:');
  710.       if (length(input)=0) or hungupon then exit;
  711.       writeln;
  712.       t:=lookupuser (input);
  713.       if t=0 then begin
  714.         writestr ('No such user!');
  715.         exit
  716.       end;
  717.       writelog (14,1,input);
  718.       writestr ('Looking in mailbox...');
  719.       last:=searchmail(0,t);
  720.       if last=0 then writestr ('No mail.');
  721.       while last<>0 do begin
  722.         seek (mfile,last);
  723.         read (mfile,m);
  724.         if sysopreadnum (last) or hungupon then exit;
  725.         last:=searchmail(last,t)
  726.       end;
  727.       writeln (^B^M'No more mail!')
  728.     end;
  729.  
  730.     procedure scanall;
  731.     var r1,r2:integer;
  732.         u:userrec;
  733.         n:mstr;
  734.     begin
  735.       r2:=filesize(mfile)-1;
  736.       writestr ('Start scanning at [1-'+strr(r2)+']:');
  737.       if length(input)=0 then r1:=1 else r1:=valu(input);
  738.       if (r1<1) or (r1>r2) then exit;
  739.       writelog (14,2,'');
  740.       while r1<filesize(mfile) do begin
  741.         seek (mfile,r1);
  742.         read (mfile,m);
  743.         if m.sentto<>0 then
  744.           if sysopreadnum (r1) then exit;
  745.         r1:=r1+1
  746.       end;
  747.       writeln (^B^M'No more mail!')
  748.     end;
  749.  
  750.     procedure groupflags;
  751.     var gn,bn,un,cnt:integer;
  752.         bname:sstr;
  753.         ac:accesstype;
  754.         g:grouprec;
  755.         u:userrec;
  756.     begin
  757.       writestr ('Grant all group members access to a sub-board'^M);
  758.       gn:=getgroupnum;
  759.       if gn=0 then exit;
  760.       writestr ('  Sub-board access name/number:');
  761.       writeln;
  762.       bname:=input;
  763.       opentempbdfile;
  764.       bn:=searchboard(bname);
  765.       closetempbdfile;
  766.       if bn=-1 then begin
  767.         writeln ('No such board!');
  768.         exit
  769.       end;
  770.       writelog (14,3,bname);
  771.       for cnt:=1 to g.nummembers do begin
  772.         un:=g.members[cnt];
  773.         writeln (lookupuname(un));
  774.         seek (ufile,un);
  775.         read (ufile,u);
  776.         setuseraccflag (u,bn,letin);
  777.         seek (ufile,un);
  778.         write (ufile,u)
  779.       end
  780.     end;
  781.  
  782.     procedure deleterange;
  783.     var first,last,num,cnt:integer;
  784.     begin
  785.       writehdr ('Mass Mail Delete');
  786.       parserange (filesize(mfile)-1,first,last);
  787.       if first=0 then exit;
  788.       num:=last-first;
  789.       if num<>1 then begin
  790.         writeln ('Warning! ',num,' pieces of mail will be deleted!');
  791.         writestr ('Are you sure? *');
  792.         if not yes then exit
  793.       end;
  794.       for cnt:=last downto first do begin
  795.         delmail (cnt);
  796.         write (cnt,' ');
  797.         if break then begin
  798.           writestr (^B^M'Aborted!');
  799.           exit
  800.         end
  801.       end;
  802.       writeln
  803.     end;
  804.  
  805.   var q:integer;
  806.   begin
  807.     repeat
  808.       q:=menu ('Sysop E-Mail','ESYSOP','QLSGD');
  809.       case q of
  810.         2:someoneelse;
  811.         3:scanall;
  812.         4:groupflags;
  813.         5:deleterange;
  814.       end
  815.     until (q=1) or hungupon;
  816.     readcatalogs
  817.   end;
  818.  
  819.   {overlay} procedure announcement;
  820.  
  821.     procedure delannouncement;
  822.     begin
  823.       if urec.emailannounce=-1 then begin
  824.         writestr (^M'You don''t HAVE an announcement.');
  825.         exit
  826.       end;
  827.       deletetext (urec.emailannounce);
  828.       urec.emailannounce:=-1;
  829.       writeurec;
  830.       writestr (^M'Deleted.')
  831.     end;
  832.  
  833.     procedure createannouncement;
  834.     var me:message;
  835.     begin
  836.       if urec.emailannounce>=0 then deletetext (urec.emailannounce);
  837.       urec.emailannounce:=editor (me,false);
  838.       writeurec
  839.     end;
  840.  
  841.   var k:char;
  842.   begin
  843.     if urec.emailannounce>=0
  844.       then showannouncement (unum)
  845.       else writestr ('You don''t have an announcement right now.');
  846.     writestr (^M'C)reate/replace, D)elete, or Q)uit:');
  847.     if length(input)=0 then exit;
  848.     k:=upcase(input[1]);
  849.     case k of
  850.       'D':delannouncement;
  851.       'C':createannouncement
  852.     end
  853.   end;
  854.  
  855.   {overlay} procedure groupediting;
  856.   var curgroup:integer;
  857.       cg:grouprec;
  858.  
  859.     procedure selectgroup;
  860.     var n:integer;
  861.         g:grouprec;
  862.     begin
  863.       delete (input,1,1);
  864.       repeat
  865.         if length(input)=0 then writestr ('Select group [?=list]:');
  866.         if length(input)=0 then exit;
  867.         if input='?' then begin
  868.           listgroups;
  869.           n:=0;
  870.           input[0]:=#0
  871.         end else begin
  872.           n:=lookupgroup (input);
  873.           if n=0 then begin
  874.             writestr ('Group not found!');
  875.             exit
  876.           end
  877.         end
  878.       until n>0;
  879.       seekgfile (n);
  880.       read (gfile,g);
  881.       if groupaccess(g) then begin
  882.         curgroup:=n;
  883.         cg:=g
  884.       end else writestr ('You can''t access that group.')
  885.     end;
  886.  
  887.     function nocurgroup:boolean;
  888.     begin
  889.       nocurgroup:=curgroup=0;
  890.       if curgroup=0 then writestr ('No group as been S)elected!')
  891.     end;
  892.  
  893.     function notcreator:boolean;
  894.     var b:boolean;
  895.     begin
  896.       if nocurgroup then b:=true else begin
  897.         b:=(unum<>cg.creator) and (not issysop);
  898.         if b then writestr ('You aren''t the creator of this group!')
  899.       end;
  900.       notcreator:=b;
  901.     end;
  902.  
  903.     procedure writecurgroup;
  904.     begin
  905.       seekgfile (curgroup);
  906.       write (gfile,cg)
  907.     end;
  908.  
  909.     procedure deletegroup;
  910.     var cnt:integer;
  911.         g:grouprec;
  912.     begin
  913.       if notcreator then exit;
  914.       writestr ('Delete group '+cg.name+': Are you sure? *');
  915.       if not yes then exit;
  916.       writelog (13,2,cg.name);
  917.       for cnt:=curgroup to filesize(gfile)-1 do begin
  918.         seekgfile (cnt+1);
  919.         read (gfile,g);
  920.         seekgfile (cnt);
  921.         write (gfile,g)
  922.       end;
  923.       seek (gfile,filesize(gfile)-1);
  924.       truncate (gfile);
  925.       curgroup:=0
  926.     end;
  927.  
  928.     procedure listmembers;
  929.     var cnt:integer;
  930.     begin
  931.       if nocurgroup then exit;
  932.       writeln ('Creator:           '^S,lookupuname (cg.creator));
  933.       writeln ('Number of members: '^S,cg.nummembers,^M);
  934.       for cnt:=1 to cg.nummembers do begin
  935.         if break then exit;
  936.         writeln (cnt:2,'. ',lookupuname (cg.members[cnt]))
  937.       end
  938.     end;
  939.  
  940.     procedure readdmember;
  941.     var n:integer;
  942.     begin
  943.       if notcreator then exit;
  944.       writestr ('User to add:');
  945.       if length(input)=0 then exit;
  946.       n:=lookupuser (input);
  947.       if n=0
  948.         then writestr ('User not found!')
  949.         else begin
  950.           addmember (cg,n);
  951.           writecurgroup
  952.         end
  953.     end;
  954.  
  955.     procedure removemember;
  956.  
  957.       procedure removemembernum (n:integer);
  958.       var cnt:integer;
  959.       begin
  960.         cg.nummembers:=cg.nummembers-1;
  961.         for cnt:=n to cg.nummembers do cg.members[cnt]:=cg.members[cnt+1];
  962.         writecurgroup;
  963.         writestr ('Member removed.')
  964.       end;
  965.  
  966.     var cnt,n:integer;
  967.     begin
  968.       if notcreator then exit;
  969.       repeat
  970.         writestr ('User to remove [?=list]:');
  971.         if length(input)=0 then exit;
  972.         if input='?' then begin
  973.           input[0]:=#0;
  974.           listmembers
  975.         end
  976.       until length(input)>0;
  977.       n:=lookupuser (input);
  978.       if n=0 then begin
  979.         writestr ('User not found!');
  980.         exit
  981.       end;
  982.       for cnt:=1 to cg.nummembers do if cg.members[cnt]=n then begin
  983.         removemembernum (cnt);
  984.         exit
  985.       end;
  986.       writestr ('User isn''t in the group!')
  987.     end;
  988.  
  989.     procedure setclass;
  990.     begin
  991.       if notcreator then exit;
  992.       writeln ('Current class: '^S,groupclassstr [cg.class],^M);
  993.       cg.class:=getgroupclass;
  994.       writecurgroup
  995.     end;
  996.  
  997.     procedure setcreator;
  998.     var m:mstr;
  999.         n:integer;
  1000.     begin
  1001.       if notcreator then exit;
  1002.       writeln ('Current creator: '^S,lookupuname(cg.creator),^M);
  1003.       writestr ('Enter new creator:');
  1004.       if length(input)=0 then exit;
  1005.       n:=lookupuser(input);
  1006.       if n=0 then begin
  1007.         writestr ('User not found!');
  1008.         exit
  1009.       end;
  1010.       cg.creator:=n;
  1011.       writecurgroup;
  1012.       if (n<>unum) and (not issysop) then curgroup:=0
  1013.     end;
  1014.  
  1015.     procedure addbylevel;
  1016.     var n,cnt:integer;
  1017.         u:userrec;
  1018.     begin
  1019.       if notcreator then exit;
  1020.       writestr ('Let in all people over level:');
  1021.       n:=valu(input);
  1022.       if n=0 then exit;
  1023.       seek (ufile,1);
  1024.       for cnt:=1 to numusers do begin
  1025.         read (ufile,u);
  1026.         if (length(u.handle)>0) and (u.level>=n) then begin
  1027.           if cg.nummembers=maxgroupsize then begin
  1028.             writestr ('Sorry, group is full!');
  1029.             exit
  1030.           end;
  1031.           addmember (cg,cnt)
  1032.         end
  1033.       end
  1034.     end;
  1035.  
  1036.   var q:integer;
  1037.   begin
  1038.     curgroup:=0;
  1039.     repeat
  1040.       write (^B^M^M^R'Group selected: '^S);
  1041.       if curgroup=0
  1042.         then writeln ('None')
  1043.         else writeln (cg.name);
  1044.       q:=menu ('Group editing','GROUP','QS*LGDVMRCAE');
  1045.       case q of
  1046.         2,3:selectgroup;
  1047.         4:listgroups;
  1048.         5:addgroup;
  1049.         6:deletegroup;
  1050.         7:listmembers;
  1051.         8:readdmember;
  1052.         9:removemember;
  1053.         10:setcreator;
  1054.         11:setclass;
  1055.         12:addbylevel
  1056.       end
  1057.     until hungupon or (q=1)
  1058.   end;
  1059.  
  1060. var q:integer;
  1061. begin
  1062.   cursection:=emailsysop;
  1063.   writehdr ('The Postal Service');
  1064.   opengfile;
  1065.   readcatalogs;
  1066.   writenummail (incoming,'incoming');
  1067.   writenummail (outgoing,'outgoing');
  1068.   lastread:=0;
  1069.   repeat
  1070.     writecurmsg;
  1071.     q:=menu ('E-Mail','EMAIL','QRSLN_%@DKAV#E@CFHGI@Z');
  1072.     if q<0
  1073.       then readnum (abs(q))
  1074.       else case q of
  1075.         2:autoreply;
  1076.         3:sendmail;
  1077.         4:listallmail;
  1078.         5:newmail;
  1079.         6:nextmail;
  1080.         7:sysopmail;
  1081.         8:deleteincoming;
  1082.         9:killoutgoing;
  1083.         10:announcement;
  1084.         11:viewoutgoing;
  1085.         13:editmailuser;
  1086.         14:copymail;
  1087.         15:forwardmail;
  1088.         16:help ('Email.hlp');
  1089.         17:groupediting;
  1090.         18:showinfos;
  1091.         19:zippymail
  1092.       end
  1093.   until hungupon or (q=1);
  1094.   close (gfile)
  1095. end;
  1096.  
  1097. begin
  1098. end.
  1099.