home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / SYSPC22.ZIP / EMAIL.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-04-04  |  24.6 KB  |  1,012 lines

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