PMDF Programmer's Reference Manual


Previous Contents Index

1.12.3 Dequeuing & Re-enqueuing Messages

The programs shown in Examples 1-8 and 1-9 will loop through all messages in a message queue, converting the body of each message and re-enqueuing the converted message back to PMDF. The conversion process involves applying the "rot13" encoding used by many news readers to encode potentially offensive message content.

Note

It is important to remember to define the PMDF_CHANNEL logical (OpenVMS) or environment variable (UNIX) to be the name of the channel (in lower case) to be serviced by this program. Also, if experimenting from your own account, do not leave this logical or environment variable defined while not experimenting --- PMDF can see it when you send mail and submit that mail as though it was enqueued by the channel given by PMDF_CHANNEL. (This is a debugging feature.)

The following items of note are identified with callouts in each of the two programs:

  1. In the event of an error, the current message being processed is deferred, any new message being enqueued is aborted, and the program exits.
  2. get_message is a routine which will return true (1) if PMDFgetMessage successfully accesses a message or false (0) otherwise. If PMDFgetMessage returns any error other than PMDF__EOF , then the check routine is invoked.
  3. read_line is a routine which will return true (1) if PMDFgetLine successfully reads a line from a message or false (0) otherwise. If PMDFreadLine returns any error other than PMDF__EOF , then the check routine is invoked.
  4. A routine to walk through the header structure, hdr , and display any header lines stored in the structure. This routine does not serve any real purpose here other than to illustrate how to walk a header structure.
  5. The infamous rot13 filter.
  6. PMDFinitialize is invoked with the ischannel argument true.
  7. PMDFgetChannelName is used to determine the name of the channel being processed. This information is later passed to PMDFstartMessageEnvelope .
  8. PMDFdequeueInitialize creates and initializes a message dequeue context.
  9. Using the get_message routine, the program loops over all messages to be processed.
  10. The envelope id for the message being processed is obtained. This envelope id will be carried over to the new message which will be enqueued.
  11. Begin a message enqueue context. This new message will be the converted form of the message to be dequeued.
  12. Set the envelope id for the new message to be that of the old message.
  13. Using PMDFgetRecipient , the program loops over the envelope "To:" address list in an accessed message.
  14. The NOTARY flags for the current envelope "To:" address are obtained with PMDFgetRecipientFlags . They are then copied over to the same envelope "To:" address in the new message by calling PMDFsetRecipientFlags and then PMDFaddRecipient .
  15. The disposition of the envelope "To:" address is declared.
  16. The envelope is ended and the message header started.
  17. PMDFreadHeader and PMDFwriteHeader is used to copy, without alteration, the message header from the old message to the new message.
  18. Call display_header_lines to display, on the terminal, the contents of the header structure, hdr . This is merely done as an example of walking through a header structure; displaying the structure serves no other useful purpose in this example.
  19. Using the read_line routine, the program loops over the message body, reading each line from the original messages, converting it, and then writing it to the new message being enqueued.
  20. The new message is enqueued and the message enqueue context disposed of.
  21. The old message is dequeued.
  22. All done processing mesages; dispose of the message dequeue context;

Example 1-8 Message Dequeuing & Re-enqueuing (Pascal)

(* api_example5.pas -- Dequeue a message, rot13 the message body, 
                       and then requeue the message *) 
 
[inherit ('pmdf_exe:apidef')] program api_example5 (output); 
 
  type 
    uword     = [word] 0..65535; 
    string    = packed array [1..ALFA_SIZE] of char; 
    bigstring = packed array [1..BIGALFA_SIZE] of char; 
 
  var 
    channel, env_id, from_adr, orig_adr, to_adr : string; 
    channel_len, env_id_len, from_adr_len, 
      orig_adr_len, to_adr_len, txt_len         : uword; 
    dq_context                                  : PMDF_dq; 
    empty                                       : varying [1] of char; 
    hdr                                         : PMDF_hdr; 
    i, nflags, stat                             : integer; 
    nq_context                                  : PMDF_nq; 
    outfile                                     : text; 
    txt                                         : bigstring; 
 
function SYS$EXIT (%immed status : integer := %immed 1) : integer; extern; 
 
procedure check (stat : integer); (1)
 
  var reason : varying [20] of char; 
 
  begin (* check *) 
    if not odd (stat) then begin 
      writev (reason, 'Reason ', stat:0); 
      if dq_context <> nil then PMDF_defer_message (dq_context, true, reason); 
      if nq_context <> nil then PMDF_abort_message (nq_context); 
      if stat = 0 then SYS$EXIT (1) else SYS$EXIT (stat); 
    end; (* if *) 
  end; (* check *) 
 
function get_message : boolean; (2)
 
  var msg_file : string; msg_file_len : uword; 
 
  begin (* get_message *) 
    stat := PMDF_get_message (dq_context, msg_file, msg_file_len, 
                              from_adr, from_adr_len); 
    get_message := odd (stat); 
    if (not odd (stat)) and (stat <> PMDF__EOF) then check (stat); 
  end; (* get_message *) 
 
function read_line : boolean; (3)
 
  begin (* read_line *) 
    stat := PMDF_read_line (dq_context, txt, txt_len); 
    read_line := odd (stat); 
    if (not odd (stat)) and (stat <> PMDF__EOF) then check (stat); 
  end; (* read_line *) 
 
procedure display_header_lines (hdr : PMDF_hdr); (4)
 
  var i : integer; hdr_line : PMDF_hdr_line_ptr; 
 
  begin (* display_header_lines *) 
    for i := HL_FIRST_HEADER to HL_LAST_HEADER do begin 
      if hdr^[i] <> nil then begin 
        hdr_line := hdr^[i]; 
        while hdr_line <> nil do begin 
          writeln (substr (hdr_line^.line^, 1, hdr_line^.line_length)); 
          hdr_line := hdr_line^.next_line; 
        end; (* while *) 
      end; (* if *) 
    end; (* for *) 
  end; (* display_header_lines *) 
 
function rot13 (c : char) : char; (5)
 
  begin (* rot13 *) 
    if c in ['A'..'Z'] then 
      rot13 := chr (((ord (c) - ord ('A') + 13) mod 26) + ord ('A')) 
    else if c in ['a'..'z'] then 
      rot13 := chr (((ord (c) - ord ('a') + 13) mod 26) + ord ('a')) 
    else rot13 := c; 
  end; (* rot13 *) 
 
begin (* api_example5 *) 
  empty         := ''; 
  hdr           := nil; 
  dq_context    := nil; 
  nq_context    := nil; 
  check (PMDF_initialize (true)); (6)
  check (PMDF_get_channel_name (channel, channel_len)); (7)
  check (PMDF_dequeue_initialize (dq_context)); (8)
  check (PMDF_enqueue_initialize); 
  while get_message do begin (9)
    check (PMDF_get_envelope_id (dq_context, env_id, env_id_len)); (10)
    check (PMDF_start_message_envelope (nq_context, (11)
                                        substr (channel, 1, channel_len), 
                                        substr (from_adr, 1, from_adr_len))); 
    check (PMDF_set_envelope_id (nq_context, substr (env_id, 1, env_id_len))); (12)
    while odd (PMDF_get_recipient (dq_context, to_adr, to_adr_len, (13)
                                   orig_adr, orig_adr_len)) do begin 
      check (PMDF_get_recipient_flags (dq_context, nflags)); (14)
      check (PMDF_set_recipient_flags (nq_context, nflags)); 
      check (PMDF_add_recipient (nq_context, substr (to_adr, 1, to_adr_len), 
                                 substr (orig_adr, 1, orig_adr_len))); 
      check (PMDF_recipient_disposition (dq_context, nflags, (15)
                                PMDF_DISP_DELIVERED, 
                                substr (to_adr, 1, to_adr_len), 
                                substr (orig_adr, 1, orig_adr_len), empty)); 
    end; (* while *) 
    check (PMDF_start_message_header (nq_context)); (16)
    check (PMDF_read_header (dq_context, hdr)); (17)
    display_header_lines (hdr); (18)
    check (PMDF_write_header (nq_context, hdr)); 
    check (PMDF_dispose_header (hdr)); 
    check (PMDF_start_message_body (nq_context)); 
    while read_line do begin (19)
      for i := 1 to txt_len do txt[i] := rot13 (txt[i]); 
      check (PMDF_write_line (nq_context, substr (txt, 1, txt_len))); 
    end; (* while *) 
    check (PMDF_enqueue_message (nq_context)); (20)
    check (PMDF_dequeue_message_end (dq_context, false, empty)); (21)
  end; (* while *) 
  check (PMDF_dequeue_end (dq_context)); (22)
  check (PMDF_done); 
end. (* api_example5 *) 
 

Example 1-9 Message Dequeuing & Re-enqueuing (C)

/* api_example6.c -- Dequeue a message, rot13 the message body, 
                     and then requeue the message */ 
 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#ifdef __VMS 
#include "pmdf_com:apidef.h" 
#else 
#include "/pmdf/include/apidef.h" 
#endif 
 
typedef char string[ALFA_SIZE+1]; 
 
string from_adr, txt; 
int from_adr_len, txt_len; 
PMDF_nq *nq_context = 0; 
PMDF_dq *dq_context = 0; 
 
void check (int stat) (1)
{ 
  char reason[20]; 
  if (!(1 & stat)) { 
    sprintf (reason, "Reason %d", stat); 
    if (dq_context) PMDFdeferMessage (&dq_context, 1, reason, strlen (reason)); 
    if (nq_context) PMDFabortMessage (&nq_context); 
    if (!stat) exit (0); 
    else exit (stat); 
  } 
} 
 
int get_message (void) (2)
{ 
    string msg_file; 
    int msg_file_len, stat; 
 
    msg_file_len = from_adr_len = ALFA_SIZE; 
    stat = PMDFgetMessage (&dq_context, msg_file, &msg_file_len, 
                           from_adr, &from_adr_len); 
    if (!(1 & stat) && stat != PMDF__EOF) check (stat); 
    return (1 & stat); 
} 
 
int read_line (void) (3)
{ 
    int stat; 
 
    txt_len = BIGALFA_SIZE; 
    stat = PMDFreadLine (&dq_context, txt, &txt_len); 
    if ( !(1 & stat) && stat != PMDF__EOF) check (stat); 
    return (1 & stat); 
} 
 
void display_header_lines (PMDF_hdr *hdr) (4)
{ 
  int i; 
  PMDF_hdr_line *hdr_line; 
 
  for (i = HL_FIRST_HEADER; i <= HL_LAST_HEADER; i++) { 
    if ((*hdr)[i]) { 
      hdr_line = (*hdr)[i]; 
      while (hdr_line) { 
        printf ("%s\n", hdr_line->line); 
        hdr_line = hdr_line->next_line; 
      } 
    } 
  } 
} 
 
char rot13 (char c) (5)
{ 
  if ('A' <= c && c <= 'Z') return (((c - 'A' + 13) % 26) + 'A'); 
    else if ('a' <= c && c <= 'z') return (((c - 'a' + 13) % 26) + 'a'); 
      else return (c); 
} 
 
main () 
{ 
  string channel, env_id, orig_adr, to_adr; 
  int channel_len, env_id_len, nflags, i, orig_adr_len, to_adr_len; 
  PMDF_hdr *hdr; 
  unsigned int key; 
 
  check (PMDFinitialize (1)); (6)
  channel_len = ALFA_SIZE; 
  check (PMDFgetChannelName (channel, &channel_len, &key, &key)); (7)
  check (PMDFdequeueInitialize (&dq_context)); (8)
  check (PMDFenqueueInitialize ()); 
  while (get_message ()) { (9)
    env_id_len = ALFA_SIZE; 
    check (PMDFgetEnvelopeId (&dq_context, env_id, &env_id_len)); (10)
    check (PMDFstartMessageEnvelope (&nq_context, channel, channel_len, (11)
                                     from_adr, from_adr_len)); 
    check (PMDFsetEnvelopeId (&nq_context, env_id, env_id_len)); (12)
    to_adr_len = orig_adr_len = ALFA_SIZE; 
    while (1 & PMDFgetRecipient (&dq_context, to_adr, &to_adr_len, (13)
                                 orig_adr, &orig_adr_len)) 
    { 
      check (PMDFgetRecipientFlags (&dq_context, &nflags)); (14)
      check (PMDFsetRecipientFlags (&nq_context, nflags)); 
      check (PMDFaddRecipient (&nq_context, to_adr, to_adr_len, 
                               orig_adr, orig_adr_len)); 
      check (PMDFrecipientDisposition (&dq_context, nflags, (15)
                                       PMDF_DISP_DELIVERED, to_adr, 
                                       to_adr_len, orig_adr, orig_adr_len, 
                                       NULL, 0)); 
      to_adr_len = orig_adr_len = ALFA_SIZE; 
    } 
    check (PMDFstartMessageHeader (&nq_context)); (16)
    check (PMDFreadHeader (&dq_context, &hdr)); (17)
    display_header_lines (hdr); (18)
    check (PMDFwriteHeader (&nq_context, hdr)); 
    check (PMDFdisposeHeader (&hdr)); 
    check (PMDFstartMessageBody (&nq_context)); 
    while (read_line ()) { (19)
      for (i = 0; i < txt_len - 1; i++) txt[i] = rot13 (txt[i]); 
      check (PMDFwriteLine (&nq_context, txt, txt_len)); 
    } 
    check (PMDFenqueueMessage (&nq_context)); (20)
    check (PMDFdequeueMessageEnd (&dq_context, 0, NULL, 0)); (21)
  } 
  check (PMDFdequeueEnd (&dq_context)); (22)
  check (PMDFdone ()); 
} 
 


Previous Next Contents Index