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

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